Basic gzip/gunzip in memory buffer examples using zlib code.
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); }
main.cpp@0:54f5be781526, 2012-10-21 (annotated)
- Committer:
- jonathonfletcher
- Date:
- Sun Oct 21 07:46:41 2012 +0000
- Revision:
- 0:54f5be781526
initial checkin
Who changed what in which revision?
User | Revision | Line number | New 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 | } |