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 /* adler32.c -- compute the Adler-32 checksum of a data stream
jonathonfletcher 0:54f5be781526 2 * Copyright (C) 1995-2011 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 /* @(#) $Id$ */
jonathonfletcher 0:54f5be781526 7
jonathonfletcher 0:54f5be781526 8 #include "zutil.h"
jonathonfletcher 0:54f5be781526 9
jonathonfletcher 0:54f5be781526 10 #define local static
jonathonfletcher 0:54f5be781526 11
jonathonfletcher 0:54f5be781526 12 local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
jonathonfletcher 0:54f5be781526 13
jonathonfletcher 0:54f5be781526 14 #define BASE 65521 /* largest prime smaller than 65536 */
jonathonfletcher 0:54f5be781526 15 #define NMAX 5552
jonathonfletcher 0:54f5be781526 16 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
jonathonfletcher 0:54f5be781526 17
jonathonfletcher 0:54f5be781526 18 #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
jonathonfletcher 0:54f5be781526 19 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
jonathonfletcher 0:54f5be781526 20 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
jonathonfletcher 0:54f5be781526 21 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
jonathonfletcher 0:54f5be781526 22 #define DO16(buf) DO8(buf,0); DO8(buf,8);
jonathonfletcher 0:54f5be781526 23
jonathonfletcher 0:54f5be781526 24 /* use NO_DIVIDE if your processor does not do division in hardware --
jonathonfletcher 0:54f5be781526 25 try it both ways to see which is faster */
jonathonfletcher 0:54f5be781526 26 #ifdef NO_DIVIDE
jonathonfletcher 0:54f5be781526 27 /* note that this assumes BASE is 65521, where 65536 % 65521 == 15
jonathonfletcher 0:54f5be781526 28 (thank you to John Reiser for pointing this out) */
jonathonfletcher 0:54f5be781526 29 # define CHOP(a) \
jonathonfletcher 0:54f5be781526 30 do { \
jonathonfletcher 0:54f5be781526 31 unsigned long tmp = a >> 16; \
jonathonfletcher 0:54f5be781526 32 a &= 0xffffUL; \
jonathonfletcher 0:54f5be781526 33 a += (tmp << 4) - tmp; \
jonathonfletcher 0:54f5be781526 34 } while (0)
jonathonfletcher 0:54f5be781526 35 # define MOD28(a) \
jonathonfletcher 0:54f5be781526 36 do { \
jonathonfletcher 0:54f5be781526 37 CHOP(a); \
jonathonfletcher 0:54f5be781526 38 if (a >= BASE) a -= BASE; \
jonathonfletcher 0:54f5be781526 39 } while (0)
jonathonfletcher 0:54f5be781526 40 # define MOD(a) \
jonathonfletcher 0:54f5be781526 41 do { \
jonathonfletcher 0:54f5be781526 42 CHOP(a); \
jonathonfletcher 0:54f5be781526 43 MOD28(a); \
jonathonfletcher 0:54f5be781526 44 } while (0)
jonathonfletcher 0:54f5be781526 45 # define MOD63(a) \
jonathonfletcher 0:54f5be781526 46 do { /* this assumes a is not negative */ \
jonathonfletcher 0:54f5be781526 47 z_off64_t tmp = a >> 32; \
jonathonfletcher 0:54f5be781526 48 a &= 0xffffffffL; \
jonathonfletcher 0:54f5be781526 49 a += (tmp << 8) - (tmp << 5) + tmp; \
jonathonfletcher 0:54f5be781526 50 tmp = a >> 16; \
jonathonfletcher 0:54f5be781526 51 a &= 0xffffL; \
jonathonfletcher 0:54f5be781526 52 a += (tmp << 4) - tmp; \
jonathonfletcher 0:54f5be781526 53 tmp = a >> 16; \
jonathonfletcher 0:54f5be781526 54 a &= 0xffffL; \
jonathonfletcher 0:54f5be781526 55 a += (tmp << 4) - tmp; \
jonathonfletcher 0:54f5be781526 56 if (a >= BASE) a -= BASE; \
jonathonfletcher 0:54f5be781526 57 } while (0)
jonathonfletcher 0:54f5be781526 58 #else
jonathonfletcher 0:54f5be781526 59 # define MOD(a) a %= BASE
jonathonfletcher 0:54f5be781526 60 # define MOD28(a) a %= BASE
jonathonfletcher 0:54f5be781526 61 # define MOD63(a) a %= BASE
jonathonfletcher 0:54f5be781526 62 #endif
jonathonfletcher 0:54f5be781526 63
jonathonfletcher 0:54f5be781526 64 /* ========================================================================= */
jonathonfletcher 0:54f5be781526 65 uLong ZEXPORT adler32(adler, buf, len)
jonathonfletcher 0:54f5be781526 66 uLong adler;
jonathonfletcher 0:54f5be781526 67 const Bytef *buf;
jonathonfletcher 0:54f5be781526 68 uInt len;
jonathonfletcher 0:54f5be781526 69 {
jonathonfletcher 0:54f5be781526 70 unsigned long sum2;
jonathonfletcher 0:54f5be781526 71 unsigned n;
jonathonfletcher 0:54f5be781526 72
jonathonfletcher 0:54f5be781526 73 /* split Adler-32 into component sums */
jonathonfletcher 0:54f5be781526 74 sum2 = (adler >> 16) & 0xffff;
jonathonfletcher 0:54f5be781526 75 adler &= 0xffff;
jonathonfletcher 0:54f5be781526 76
jonathonfletcher 0:54f5be781526 77 /* in case user likes doing a byte at a time, keep it fast */
jonathonfletcher 0:54f5be781526 78 if (len == 1) {
jonathonfletcher 0:54f5be781526 79 adler += buf[0];
jonathonfletcher 0:54f5be781526 80 if (adler >= BASE)
jonathonfletcher 0:54f5be781526 81 adler -= BASE;
jonathonfletcher 0:54f5be781526 82 sum2 += adler;
jonathonfletcher 0:54f5be781526 83 if (sum2 >= BASE)
jonathonfletcher 0:54f5be781526 84 sum2 -= BASE;
jonathonfletcher 0:54f5be781526 85 return adler | (sum2 << 16);
jonathonfletcher 0:54f5be781526 86 }
jonathonfletcher 0:54f5be781526 87
jonathonfletcher 0:54f5be781526 88 /* initial Adler-32 value (deferred check for len == 1 speed) */
jonathonfletcher 0:54f5be781526 89 if (buf == Z_NULL)
jonathonfletcher 0:54f5be781526 90 return 1L;
jonathonfletcher 0:54f5be781526 91
jonathonfletcher 0:54f5be781526 92 /* in case short lengths are provided, keep it somewhat fast */
jonathonfletcher 0:54f5be781526 93 if (len < 16) {
jonathonfletcher 0:54f5be781526 94 while (len--) {
jonathonfletcher 0:54f5be781526 95 adler += *buf++;
jonathonfletcher 0:54f5be781526 96 sum2 += adler;
jonathonfletcher 0:54f5be781526 97 }
jonathonfletcher 0:54f5be781526 98 if (adler >= BASE)
jonathonfletcher 0:54f5be781526 99 adler -= BASE;
jonathonfletcher 0:54f5be781526 100 MOD28(sum2); /* only added so many BASE's */
jonathonfletcher 0:54f5be781526 101 return adler | (sum2 << 16);
jonathonfletcher 0:54f5be781526 102 }
jonathonfletcher 0:54f5be781526 103
jonathonfletcher 0:54f5be781526 104 /* do length NMAX blocks -- requires just one modulo operation */
jonathonfletcher 0:54f5be781526 105 while (len >= NMAX) {
jonathonfletcher 0:54f5be781526 106 len -= NMAX;
jonathonfletcher 0:54f5be781526 107 n = NMAX / 16; /* NMAX is divisible by 16 */
jonathonfletcher 0:54f5be781526 108 do {
jonathonfletcher 0:54f5be781526 109 DO16(buf); /* 16 sums unrolled */
jonathonfletcher 0:54f5be781526 110 buf += 16;
jonathonfletcher 0:54f5be781526 111 } while (--n);
jonathonfletcher 0:54f5be781526 112 MOD(adler);
jonathonfletcher 0:54f5be781526 113 MOD(sum2);
jonathonfletcher 0:54f5be781526 114 }
jonathonfletcher 0:54f5be781526 115
jonathonfletcher 0:54f5be781526 116 /* do remaining bytes (less than NMAX, still just one modulo) */
jonathonfletcher 0:54f5be781526 117 if (len) { /* avoid modulos if none remaining */
jonathonfletcher 0:54f5be781526 118 while (len >= 16) {
jonathonfletcher 0:54f5be781526 119 len -= 16;
jonathonfletcher 0:54f5be781526 120 DO16(buf);
jonathonfletcher 0:54f5be781526 121 buf += 16;
jonathonfletcher 0:54f5be781526 122 }
jonathonfletcher 0:54f5be781526 123 while (len--) {
jonathonfletcher 0:54f5be781526 124 adler += *buf++;
jonathonfletcher 0:54f5be781526 125 sum2 += adler;
jonathonfletcher 0:54f5be781526 126 }
jonathonfletcher 0:54f5be781526 127 MOD(adler);
jonathonfletcher 0:54f5be781526 128 MOD(sum2);
jonathonfletcher 0:54f5be781526 129 }
jonathonfletcher 0:54f5be781526 130
jonathonfletcher 0:54f5be781526 131 /* return recombined sums */
jonathonfletcher 0:54f5be781526 132 return adler | (sum2 << 16);
jonathonfletcher 0:54f5be781526 133 }
jonathonfletcher 0:54f5be781526 134
jonathonfletcher 0:54f5be781526 135 /* ========================================================================= */
jonathonfletcher 0:54f5be781526 136 local uLong adler32_combine_(adler1, adler2, len2)
jonathonfletcher 0:54f5be781526 137 uLong adler1;
jonathonfletcher 0:54f5be781526 138 uLong adler2;
jonathonfletcher 0:54f5be781526 139 z_off64_t len2;
jonathonfletcher 0:54f5be781526 140 {
jonathonfletcher 0:54f5be781526 141 unsigned long sum1;
jonathonfletcher 0:54f5be781526 142 unsigned long sum2;
jonathonfletcher 0:54f5be781526 143 unsigned rem;
jonathonfletcher 0:54f5be781526 144
jonathonfletcher 0:54f5be781526 145 /* for negative len, return invalid adler32 as a clue for debugging */
jonathonfletcher 0:54f5be781526 146 if (len2 < 0)
jonathonfletcher 0:54f5be781526 147 return 0xffffffffUL;
jonathonfletcher 0:54f5be781526 148
jonathonfletcher 0:54f5be781526 149 /* the derivation of this formula is left as an exercise for the reader */
jonathonfletcher 0:54f5be781526 150 MOD63(len2); /* assumes len2 >= 0 */
jonathonfletcher 0:54f5be781526 151 rem = (unsigned)len2;
jonathonfletcher 0:54f5be781526 152 sum1 = adler1 & 0xffff;
jonathonfletcher 0:54f5be781526 153 sum2 = rem * sum1;
jonathonfletcher 0:54f5be781526 154 MOD(sum2);
jonathonfletcher 0:54f5be781526 155 sum1 += (adler2 & 0xffff) + BASE - 1;
jonathonfletcher 0:54f5be781526 156 sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
jonathonfletcher 0:54f5be781526 157 if (sum1 >= BASE) sum1 -= BASE;
jonathonfletcher 0:54f5be781526 158 if (sum1 >= BASE) sum1 -= BASE;
jonathonfletcher 0:54f5be781526 159 if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
jonathonfletcher 0:54f5be781526 160 if (sum2 >= BASE) sum2 -= BASE;
jonathonfletcher 0:54f5be781526 161 return sum1 | (sum2 << 16);
jonathonfletcher 0:54f5be781526 162 }
jonathonfletcher 0:54f5be781526 163
jonathonfletcher 0:54f5be781526 164 /* ========================================================================= */
jonathonfletcher 0:54f5be781526 165 uLong ZEXPORT adler32_combine(adler1, adler2, len2)
jonathonfletcher 0:54f5be781526 166 uLong adler1;
jonathonfletcher 0:54f5be781526 167 uLong adler2;
jonathonfletcher 0:54f5be781526 168 z_off_t len2;
jonathonfletcher 0:54f5be781526 169 {
jonathonfletcher 0:54f5be781526 170 return adler32_combine_(adler1, adler2, len2);
jonathonfletcher 0:54f5be781526 171 }
jonathonfletcher 0:54f5be781526 172
jonathonfletcher 0:54f5be781526 173 uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
jonathonfletcher 0:54f5be781526 174 uLong adler1;
jonathonfletcher 0:54f5be781526 175 uLong adler2;
jonathonfletcher 0:54f5be781526 176 z_off64_t len2;
jonathonfletcher 0:54f5be781526 177 {
jonathonfletcher 0:54f5be781526 178 return adler32_combine_(adler1, adler2, len2);
jonathonfletcher 0:54f5be781526 179 }