Created
May 10, 2013 08:40
-
-
Save niklasberglund/5553224 to your computer and use it in GitHub Desktop.
NSData category adding gzip functionality. Extracted from http://cocoadev.com/wiki/NSDataCategory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface NSData (gzip) | |
- (NSData *)gzipInflate; | |
- (NSData *)gzipDeflate; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "NSData+gzip.h" | |
#include <zlib.h> | |
@implementation NSData (gzip) | |
- (NSData *)gzipInflate | |
{ | |
if ([self length] == 0) return self; | |
unsigned full_length = [self length]; | |
unsigned half_length = [self length] / 2; | |
NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; | |
BOOL done = NO; | |
int status; | |
z_stream strm; | |
strm.next_in = (Bytef *)[self bytes]; | |
strm.avail_in = [self length]; | |
strm.total_out = 0; | |
strm.zalloc = Z_NULL; | |
strm.zfree = Z_NULL; | |
if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; | |
while (!done) | |
{ | |
// Make sure we have enough room and reset the lengths. | |
if (strm.total_out >= [decompressed length]) | |
[decompressed increaseLengthBy: half_length]; | |
strm.next_out = [decompressed mutableBytes] + strm.total_out; | |
strm.avail_out = [decompressed length] - strm.total_out; | |
// Inflate another chunk. | |
status = inflate (&strm, Z_SYNC_FLUSH); | |
if (status == Z_STREAM_END) done = YES; | |
else if (status != Z_OK) break; | |
} | |
if (inflateEnd (&strm) != Z_OK) return nil; | |
// Set real length. | |
if (done) | |
{ | |
[decompressed setLength: strm.total_out]; | |
return [NSData dataWithData: decompressed]; | |
} | |
else return nil; | |
} | |
- (NSData *)gzipDeflate | |
{ | |
if ([self length] == 0) return self; | |
z_stream strm; | |
strm.zalloc = Z_NULL; | |
strm.zfree = Z_NULL; | |
strm.opaque = Z_NULL; | |
strm.total_out = 0; | |
strm.next_in=(Bytef *)[self bytes]; | |
strm.avail_in = [self length]; | |
// Compresssion Levels: | |
// Z_NO_COMPRESSION | |
// Z_BEST_SPEED | |
// Z_BEST_COMPRESSION | |
// Z_DEFAULT_COMPRESSION | |
if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil; | |
NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion | |
do { | |
if (strm.total_out >= [compressed length]) | |
[compressed increaseLengthBy: 16384]; | |
strm.next_out = [compressed mutableBytes] + strm.total_out; | |
strm.avail_out = [compressed length] - strm.total_out; | |
deflate(&strm, Z_FINISH); | |
} while (strm.avail_out == 0); | |
deflateEnd(&strm); | |
[compressed setLength: strm.total_out]; | |
return [NSData dataWithData:compressed]; | |
} | |
@end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment