iOS web browser with a focus on security and privacy
1/*
2 * Based on public domain example and information on the CocoaDev Wiki:
3 * http://cocoadev.com/wiki/NSDataCategory
4 */
5
6#import "NSData+CocoaDevUsersAdditions.h"
7#include <zlib.h>
8
9#define FUNC_GZIP 2
10#define FUNC_INFLATE 1
11
12@implementation NSData (NSDataExtension)
13
14- (NSData *)inflateWithFunction:(int)func
15{
16 if ([self length] == 0)
17 return self;
18
19 unsigned int full_length = (unsigned int)[self length];
20 unsigned int half_length = (unsigned int)([self length] / 2);
21
22 NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
23 BOOL done = NO;
24 int status;
25
26 z_stream strm;
27 strm.next_in = (Bytef *)[self bytes];
28 strm.avail_in = (unsigned int)[self length];
29 strm.total_out = 0;
30 strm.zalloc = Z_NULL;
31 strm.zfree = Z_NULL;
32
33 if (func == FUNC_INFLATE) {
34 if (inflateInit(&strm) != Z_OK)
35 return nil;
36 }
37 else if (func == FUNC_GZIP) {
38 if (inflateInit2(&strm, (15+32)) != Z_OK)
39 return nil;
40 }
41 else
42 return nil;
43
44 while (!done) {
45 // Make sure we have enough room and reset the lengths.
46 if (strm.total_out >= [decompressed length])
47 [decompressed increaseLengthBy: half_length];
48 strm.next_out = [decompressed mutableBytes] + strm.total_out;
49 strm.avail_out = (unsigned int)([decompressed length] - strm.total_out);
50
51 // Inflate another chunk.
52 status = inflate(&strm, Z_SYNC_FLUSH);
53 if (status == Z_STREAM_END)
54 done = YES;
55 else if (status != Z_OK)
56 break;
57 }
58 if (inflateEnd(&strm) != Z_OK)
59 return nil;
60
61 // Set real length.
62 if (done) {
63 [decompressed setLength:strm.total_out];
64 return [NSData dataWithData:decompressed];
65 }
66
67 return nil;
68}
69
70- (NSData *)zlibInflate
71{
72 return [self inflateWithFunction:FUNC_INFLATE];
73}
74
75- (NSData *)gzipInflate
76{
77 return [self inflateWithFunction:FUNC_GZIP];
78}
79
80@end