Fixing zlib inflate and deflate NSData category methods
This commit is contained in:
parent
9ee84844c4
commit
04dad96904
1 changed files with 72 additions and 61 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue