Browse Source

Fixing zlib inflate and deflate NSData category methods

Mattt Thompson 14 years ago
parent
commit
04dad96904
1 changed files with 72 additions and 61 deletions
  1. 72 61
      AFNetworking/NSData+AFNetworking.m

+ 72 - 61
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