Skip to content

Commit

Permalink
Fixing zlib inflate and deflate NSData category methods
Browse files Browse the repository at this point in the history
  • Loading branch information
mattt committed Sep 17, 2011
1 parent 686854b commit 75a0e19
Showing 1 changed file with 72 additions and 61 deletions.
133 changes: 72 additions & 61 deletions AFNetworking/NSData+AFNetworking.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,65 +29,6 @@

static char Base64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static inline NSUInteger NSDataEstimatedCompressedLength(NSData *data) {
return [data length] / 2;
}

typedef enum {
GzipDeflate = -1,
GzipInflate = 1,
} GzipOperation;

@interface NSData (_AFNetworking)
+ (NSData *)dataByTransformingData:(NSData *)data
usingGZipOperation:(GzipOperation)operation
error:(NSError **)error;
@end

@implementation NSData (_AFNetworking)

+ (NSData *)dataByTransformingData:(NSData *)data
usingGZipOperation:(GzipOperation)operation
error:(NSError **)error
{
z_stream zStream;

NSUInteger estimatedLength = NSDataEstimatedCompressedLength(data);
NSMutableData *mutableData = [NSMutableData dataWithLength:estimatedLength];

int status;
zStream.next_in = (Bytef *)[data bytes];
zStream.avail_in = (unsigned int)[data length];
zStream.avail_out = 0;

NSInteger bytesProcessedAlready = zStream.total_out;
while (zStream.avail_out == 0) {
if (zStream.total_out - bytesProcessedAlready >= [mutableData length]) {
[mutableData increaseLengthBy:estimatedLength / 2];
}

zStream.next_out = [mutableData mutableBytes] + zStream.total_out-bytesProcessedAlready;
zStream.avail_out = (unsigned int)([mutableData length] - (zStream.total_out-bytesProcessedAlready));
status = deflate(&zStream, Z_FINISH);

if (status == Z_STREAM_END) {
break;
} else if (status != Z_OK) {
if (error) {
*error = [NSError errorWithDomain:AFZlibErrorDomain code:status userInfo:nil];
}

return nil;
}
}

[mutableData setLength:zStream.total_out - bytesProcessedAlready];

return mutableData;
}

@end

#pragma mark -

@implementation NSData (AFNetworking)
Expand Down Expand Up @@ -120,11 +61,81 @@ - (NSString *)base64EncodedString {
}

- (NSData *)dataByGZipCompressingWithError:(NSError **)error {
return [NSData dataByTransformingData:self usingGZipOperation:GzipDeflate error:error];
if ([self length] == 0) {
return self;
}

z_stream zStream;

zStream.zalloc = Z_NULL;
zStream.zfree = Z_NULL;
zStream.opaque = Z_NULL;
zStream.next_in = (Bytef *)[self bytes];
zStream.avail_in = [self length];
zStream.total_out = 0;

if (deflateInit(&zStream, Z_DEFAULT_COMPRESSION) != Z_OK) {
return nil;
}

NSUInteger compressionChunkSize = 16384; // 16Kb
NSMutableData *compressedData = [NSMutableData dataWithLength:compressionChunkSize];

do {
if (zStream.total_out >= [compressedData length]) {
[compressedData increaseLengthBy:compressionChunkSize];
}

zStream.next_out = [compressedData mutableBytes] + zStream.total_out;
zStream.avail_out = [compressedData length] - zStream.total_out;

deflate(&zStream, Z_FINISH);

} while (zStream.avail_out == 0);

deflateEnd(&zStream);
[compressedData setLength:zStream.total_out];

return [NSData dataWithData:compressedData];
}

- (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error {
return [NSData dataByTransformingData:self usingGZipOperation:GzipInflate error:error];
z_stream zStream;

zStream.zalloc = Z_NULL;
zStream.zfree = Z_NULL;
zStream.next_in = (Bytef *)[self bytes];
zStream.avail_in = [self length];
zStream.avail_out = 0;
zStream.total_out = 0;

NSUInteger estimatedLength = [self length] / 2;
NSMutableData *decompressedData = [NSMutableData dataWithLength:estimatedLength];

do {
if (zStream.total_out >= [decompressedData length]) {
[decompressedData increaseLengthBy:estimatedLength / 2];
}

zStream.next_out = [decompressedData mutableBytes] + zStream.total_out;
zStream.avail_out = [decompressedData length] - zStream.total_out;

int status = inflate(&zStream, Z_FINISH);

if (status == Z_STREAM_END) {
break;
} else if (status != Z_OK) {
if (error) {
*error = [NSError errorWithDomain:AFZlibErrorDomain code:status userInfo:nil];
}

return nil;
}
} while (zStream.avail_out == 0);

[decompressedData setLength:zStream.total_out];

return [NSData dataWithData:decompressedData];
}

@end

0 comments on commit 75a0e19

Please sign in to comment.