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 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 -
|
#pragma mark -
|
||||||
|
|
||||||
@implementation NSData (AFNetworking)
|
@implementation NSData (AFNetworking)
|
||||||
|
|
@ -120,11 +61,81 @@ typedef enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)dataByGZipCompressingWithError:(NSError **)error {
|
- (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 {
|
- (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
|
@end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue