diff --git a/AFNetworking/NSData+AFNetworking.m b/AFNetworking/NSData+AFNetworking.m index 13ba284..da43a49 100644 --- a/AFNetworking/NSData+AFNetworking.m +++ b/AFNetworking/NSData+AFNetworking.m @@ -29,65 +29,6 @@ NSString * const AFZlibErrorDomain = @"com.alamofire.networking.zlib.error"; 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) @@ -120,11 +61,81 @@ typedef enum { } - (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