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 #include "mbed.h"
jonathonfletcher 0:54f5be781526 2 #include "rtos.h"
jonathonfletcher 0:54f5be781526 3
jonathonfletcher 0:54f5be781526 4 #include "zlib.h"
jonathonfletcher 0:54f5be781526 5
jonathonfletcher 0:54f5be781526 6
jonathonfletcher 0:54f5be781526 7 static const char *newline = "\r\n";
jonathonfletcher 0:54f5be781526 8
jonathonfletcher 0:54f5be781526 9
jonathonfletcher 0:54f5be781526 10 BusOut leds(LED1, LED2, LED3, LED4);
jonathonfletcher 0:54f5be781526 11 LocalFileSystem fs("local");
jonathonfletcher 0:54f5be781526 12
jonathonfletcher 0:54f5be781526 13
jonathonfletcher 0:54f5be781526 14
jonathonfletcher 0:54f5be781526 15 /** GUNZIP a from src buffer to dst buffer
jonathonfletcher 0:54f5be781526 16 @param dst : destination buffer
jonathonfletcher 0:54f5be781526 17 @param dst_length : pointer to destination buffer length
jonathonfletcher 0:54f5be781526 18 @param src : source buffer
jonathonfletcher 0:54f5be781526 19 @param src_length : source buffer length
jonathonfletcher 0:54f5be781526 20 @return Z_OK on success, zlib error (<0) on failure
jonathonfletcher 0:54f5be781526 21 */
jonathonfletcher 0:54f5be781526 22 int gunzip(unsigned char *dst, unsigned long *dst_length, unsigned char *src, unsigned long src_length)
jonathonfletcher 0:54f5be781526 23 {
jonathonfletcher 0:54f5be781526 24 z_stream stream;
jonathonfletcher 0:54f5be781526 25 memset(&stream, 0, sizeof(stream));
jonathonfletcher 0:54f5be781526 26
jonathonfletcher 0:54f5be781526 27 stream.next_in = src;
jonathonfletcher 0:54f5be781526 28 stream.avail_in = src_length;
jonathonfletcher 0:54f5be781526 29
jonathonfletcher 0:54f5be781526 30 stream.next_out = dst;
jonathonfletcher 0:54f5be781526 31 stream.avail_out = *dst_length;
jonathonfletcher 0:54f5be781526 32
jonathonfletcher 0:54f5be781526 33 int rv = inflateInit2(&stream, 15 + 16);
jonathonfletcher 0:54f5be781526 34 if (Z_OK == rv) {
jonathonfletcher 0:54f5be781526 35 rv = inflate(&stream, Z_NO_FLUSH);
jonathonfletcher 0:54f5be781526 36 if (Z_STREAM_END == rv) {
jonathonfletcher 0:54f5be781526 37 inflateEnd(&stream);
jonathonfletcher 0:54f5be781526 38 rv = Z_OK;
jonathonfletcher 0:54f5be781526 39 }
jonathonfletcher 0:54f5be781526 40 }
jonathonfletcher 0:54f5be781526 41
jonathonfletcher 0:54f5be781526 42 if (Z_OK == rv) {
jonathonfletcher 0:54f5be781526 43 *dst_length = stream.total_out;
jonathonfletcher 0:54f5be781526 44 } else {
jonathonfletcher 0:54f5be781526 45 *dst_length = 0;
jonathonfletcher 0:54f5be781526 46 }
jonathonfletcher 0:54f5be781526 47
jonathonfletcher 0:54f5be781526 48 return rv;
jonathonfletcher 0:54f5be781526 49 }
jonathonfletcher 0:54f5be781526 50
jonathonfletcher 0:54f5be781526 51 /** GUNZIP a from src buffer to dst buffer
jonathonfletcher 0:54f5be781526 52 @param dst : destination buffer
jonathonfletcher 0:54f5be781526 53 @param dst_length : pointer to destination buffer length
jonathonfletcher 0:54f5be781526 54 @param src : source buffer
jonathonfletcher 0:54f5be781526 55 @param src_length : source buffer length
jonathonfletcher 0:54f5be781526 56 @return Z_OK on success, zlib error (<0) on failure
jonathonfletcher 0:54f5be781526 57 */
jonathonfletcher 0:54f5be781526 58 int gzip(unsigned char *dst, unsigned long *dst_length, unsigned char *src, unsigned long src_length)
jonathonfletcher 0:54f5be781526 59 {
jonathonfletcher 0:54f5be781526 60 z_stream stream;
jonathonfletcher 0:54f5be781526 61 memset(&stream, 0, sizeof(stream));
jonathonfletcher 0:54f5be781526 62
jonathonfletcher 0:54f5be781526 63 stream.next_in = src;
jonathonfletcher 0:54f5be781526 64 stream.avail_in = src_length;
jonathonfletcher 0:54f5be781526 65
jonathonfletcher 0:54f5be781526 66 stream.next_out = Z_NULL;
jonathonfletcher 0:54f5be781526 67 stream.avail_out = 0;
jonathonfletcher 0:54f5be781526 68
jonathonfletcher 0:54f5be781526 69 /* add 16 to MAX_WBITS to specify gzip format - it gets taken off again in defaultInit2 */
jonathonfletcher 0:54f5be781526 70 int rv = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 16 + MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
jonathonfletcher 0:54f5be781526 71 if (Z_OK == rv) {
jonathonfletcher 0:54f5be781526 72 unsigned long dst_bound = deflateBound(&stream, stream.avail_in) + 12; /* 12 bytes for the gzip header */
jonathonfletcher 0:54f5be781526 73 if (dst_bound > *dst_length) {
jonathonfletcher 0:54f5be781526 74 rv = Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 75 } else {
jonathonfletcher 0:54f5be781526 76 stream.next_out = dst;
jonathonfletcher 0:54f5be781526 77 stream.avail_out = dst_bound;
jonathonfletcher 0:54f5be781526 78 }
jonathonfletcher 0:54f5be781526 79 }
jonathonfletcher 0:54f5be781526 80
jonathonfletcher 0:54f5be781526 81 if (Z_OK == rv) {
jonathonfletcher 0:54f5be781526 82 gz_header header;
jonathonfletcher 0:54f5be781526 83 memset(&header, 0, sizeof(header));
jonathonfletcher 0:54f5be781526 84 rv = deflateSetHeader(&stream, &header);
jonathonfletcher 0:54f5be781526 85 }
jonathonfletcher 0:54f5be781526 86
jonathonfletcher 0:54f5be781526 87 if (Z_OK == rv) {
jonathonfletcher 0:54f5be781526 88 rv = deflate(&stream, Z_FINISH);
jonathonfletcher 0:54f5be781526 89 if (Z_STREAM_END == rv) {
jonathonfletcher 0:54f5be781526 90 rv = deflateEnd(&stream);
jonathonfletcher 0:54f5be781526 91 }
jonathonfletcher 0:54f5be781526 92 }
jonathonfletcher 0:54f5be781526 93
jonathonfletcher 0:54f5be781526 94 if (Z_OK == rv) {
jonathonfletcher 0:54f5be781526 95 *dst_length = stream.total_out;
jonathonfletcher 0:54f5be781526 96 } else {
jonathonfletcher 0:54f5be781526 97 *dst_length = 0;
jonathonfletcher 0:54f5be781526 98 }
jonathonfletcher 0:54f5be781526 99
jonathonfletcher 0:54f5be781526 100 return rv;
jonathonfletcher 0:54f5be781526 101 }
jonathonfletcher 0:54f5be781526 102
jonathonfletcher 0:54f5be781526 103
jonathonfletcher 0:54f5be781526 104 int main(int argc, char**argv)
jonathonfletcher 0:54f5be781526 105 {
jonathonfletcher 0:54f5be781526 106
jonathonfletcher 0:54f5be781526 107 unsigned char input_data[2048];
jonathonfletcher 0:54f5be781526 108 unsigned long input_data_length = 0;
jonathonfletcher 0:54f5be781526 109 FILE *ifp = fopen("/local/src.txt", "r");
jonathonfletcher 0:54f5be781526 110 if (ifp) {
jonathonfletcher 0:54f5be781526 111 int br = fread(input_data, 1, sizeof(input_data), ifp);
jonathonfletcher 0:54f5be781526 112 fclose(ifp);
jonathonfletcher 0:54f5be781526 113 input_data_length = br;
jonathonfletcher 0:54f5be781526 114 }
jonathonfletcher 0:54f5be781526 115 printf("%s:%d: input_data_length:%lu%s", __FILE__, __LINE__, input_data_length, newline);
jonathonfletcher 0:54f5be781526 116
jonathonfletcher 0:54f5be781526 117
jonathonfletcher 0:54f5be781526 118 unsigned char gzip_data[2048];
jonathonfletcher 0:54f5be781526 119 unsigned long gzip_data_length = 0;
jonathonfletcher 0:54f5be781526 120 if (input_data_length > 0) {
jonathonfletcher 0:54f5be781526 121 gzip_data_length = sizeof(gzip_data);
jonathonfletcher 0:54f5be781526 122 int rv = gzip(gzip_data, &gzip_data_length, input_data, input_data_length);
jonathonfletcher 0:54f5be781526 123 if (Z_OK == rv) {
jonathonfletcher 0:54f5be781526 124 FILE *ofp = fopen("/local/dst.gz", "w");
jonathonfletcher 0:54f5be781526 125 if (ofp) {
jonathonfletcher 0:54f5be781526 126 int bw = fwrite(gzip_data, 1, gzip_data_length, ofp);
jonathonfletcher 0:54f5be781526 127 fclose(ofp);
jonathonfletcher 0:54f5be781526 128 }
jonathonfletcher 0:54f5be781526 129 } else {
jonathonfletcher 0:54f5be781526 130 printf("%s:%d: %d%s", __FILE__, __LINE__, rv, newline);
jonathonfletcher 0:54f5be781526 131 }
jonathonfletcher 0:54f5be781526 132 }
jonathonfletcher 0:54f5be781526 133 printf("%s:%d: gzip_data_length:%lu%s", __FILE__, __LINE__, gzip_data_length, newline);
jonathonfletcher 0:54f5be781526 134
jonathonfletcher 0:54f5be781526 135
jonathonfletcher 0:54f5be781526 136 unsigned char output_data[2048];
jonathonfletcher 0:54f5be781526 137 unsigned long output_data_length = 0;
jonathonfletcher 0:54f5be781526 138 if (gzip_data_length > 0) {
jonathonfletcher 0:54f5be781526 139 output_data_length = sizeof(output_data);
jonathonfletcher 0:54f5be781526 140 int rv = gunzip(output_data, &output_data_length, gzip_data, gzip_data_length);
jonathonfletcher 0:54f5be781526 141 if (Z_OK != rv) {
jonathonfletcher 0:54f5be781526 142 printf("%s:%d: %d%s", __FILE__, __LINE__, rv, newline);
jonathonfletcher 0:54f5be781526 143 }
jonathonfletcher 0:54f5be781526 144 }
jonathonfletcher 0:54f5be781526 145 printf("%s:%d: output_data_length:%lu%s", __FILE__, __LINE__, output_data_length, newline);
jonathonfletcher 0:54f5be781526 146
jonathonfletcher 0:54f5be781526 147
jonathonfletcher 0:54f5be781526 148 if (input_data_length > 0 and input_data_length > 0) {
jonathonfletcher 0:54f5be781526 149 bool input_matches_output = false;
jonathonfletcher 0:54f5be781526 150 if (input_data_length == output_data_length) {
jonathonfletcher 0:54f5be781526 151 input_matches_output = true;
jonathonfletcher 0:54f5be781526 152 for ( size_t i = 0 ; input_matches_output && i < input_data_length ; i++ ) {
jonathonfletcher 0:54f5be781526 153 if (input_data[i] != output_data[i]) {
jonathonfletcher 0:54f5be781526 154 input_matches_output = false;
jonathonfletcher 0:54f5be781526 155 }
jonathonfletcher 0:54f5be781526 156 }
jonathonfletcher 0:54f5be781526 157 }
jonathonfletcher 0:54f5be781526 158 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);
jonathonfletcher 0:54f5be781526 159 } else {
jonathonfletcher 0:54f5be781526 160 printf("%s:%d: input and/or output length is 0%s", __FILE__, __LINE__, newline);
jonathonfletcher 0:54f5be781526 161 }
jonathonfletcher 0:54f5be781526 162
jonathonfletcher 0:54f5be781526 163 while (true) {
jonathonfletcher 0:54f5be781526 164 leds = (leds ^ 1);
jonathonfletcher 0:54f5be781526 165 Thread::wait(1000);
jonathonfletcher 0:54f5be781526 166 }
jonathonfletcher 0:54f5be781526 167 }