New file |
| | |
| | | // |
| | | // NSData+YYAdd.m |
| | | // YYCategories <https://github.com/ibireme/YYCategories> |
| | | // |
| | | // Created by ibireme on 13/4/4. |
| | | // Copyright (c) 2015 ibireme. |
| | | // |
| | | // This source code is licensed under the MIT-style license found in the |
| | | // LICENSE file in the root directory of this source tree. |
| | | // |
| | | |
| | | #import "NSData+YYAdd.h" |
| | | #import "YYCategoriesMacro.h" |
| | | #include <CommonCrypto/CommonCrypto.h> |
| | | #include <zlib.h> |
| | | |
| | | YYSYNTH_DUMMY_CLASS(NSData_YYAdd) |
| | | |
| | | |
| | | @implementation NSData (YYAdd) |
| | | |
| | | - (NSString *)md2String { |
| | | unsigned char result[CC_MD2_DIGEST_LENGTH]; |
| | | CC_MD2(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSString stringWithFormat: |
| | | @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
| | | result[0], result[1], result[2], result[3], |
| | | result[4], result[5], result[6], result[7], |
| | | result[8], result[9], result[10], result[11], |
| | | result[12], result[13], result[14], result[15] |
| | | ]; |
| | | } |
| | | |
| | | - (NSData *)md2Data { |
| | | unsigned char result[CC_MD2_DIGEST_LENGTH]; |
| | | CC_MD2(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_MD2_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)md4String { |
| | | unsigned char result[CC_MD4_DIGEST_LENGTH]; |
| | | CC_MD4(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSString stringWithFormat: |
| | | @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
| | | result[0], result[1], result[2], result[3], |
| | | result[4], result[5], result[6], result[7], |
| | | result[8], result[9], result[10], result[11], |
| | | result[12], result[13], result[14], result[15] |
| | | ]; |
| | | } |
| | | |
| | | - (NSData *)md4Data { |
| | | unsigned char result[CC_MD4_DIGEST_LENGTH]; |
| | | CC_MD4(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_MD4_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)md5String { |
| | | unsigned char result[CC_MD5_DIGEST_LENGTH]; |
| | | CC_MD5(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSString stringWithFormat: |
| | | @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
| | | result[0], result[1], result[2], result[3], |
| | | result[4], result[5], result[6], result[7], |
| | | result[8], result[9], result[10], result[11], |
| | | result[12], result[13], result[14], result[15] |
| | | ]; |
| | | } |
| | | |
| | | - (NSData *)md5Data { |
| | | unsigned char result[CC_MD5_DIGEST_LENGTH]; |
| | | CC_MD5(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)sha1String { |
| | | unsigned char result[CC_SHA1_DIGEST_LENGTH]; |
| | | CC_SHA1(self.bytes, (CC_LONG)self.length, result); |
| | | NSMutableString *hash = [NSMutableString |
| | | stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; |
| | | for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { |
| | | [hash appendFormat:@"%02x", result[i]]; |
| | | } |
| | | return hash; |
| | | } |
| | | |
| | | - (NSData *)sha1Data { |
| | | unsigned char result[CC_SHA1_DIGEST_LENGTH]; |
| | | CC_SHA1(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)sha224String { |
| | | unsigned char result[CC_SHA224_DIGEST_LENGTH]; |
| | | CC_SHA224(self.bytes, (CC_LONG)self.length, result); |
| | | NSMutableString *hash = [NSMutableString |
| | | stringWithCapacity:CC_SHA224_DIGEST_LENGTH * 2]; |
| | | for (int i = 0; i < CC_SHA224_DIGEST_LENGTH; i++) { |
| | | [hash appendFormat:@"%02x", result[i]]; |
| | | } |
| | | return hash; |
| | | } |
| | | |
| | | - (NSData *)sha224Data { |
| | | unsigned char result[CC_SHA224_DIGEST_LENGTH]; |
| | | CC_SHA224(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_SHA224_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)sha256String { |
| | | unsigned char result[CC_SHA256_DIGEST_LENGTH]; |
| | | CC_SHA256(self.bytes, (CC_LONG)self.length, result); |
| | | NSMutableString *hash = [NSMutableString |
| | | stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; |
| | | for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { |
| | | [hash appendFormat:@"%02x", result[i]]; |
| | | } |
| | | return hash; |
| | | } |
| | | |
| | | - (NSData *)sha256Data { |
| | | unsigned char result[CC_SHA256_DIGEST_LENGTH]; |
| | | CC_SHA256(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_SHA256_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)sha384String { |
| | | unsigned char result[CC_SHA384_DIGEST_LENGTH]; |
| | | CC_SHA384(self.bytes, (CC_LONG)self.length, result); |
| | | NSMutableString *hash = [NSMutableString |
| | | stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2]; |
| | | for (int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++) { |
| | | [hash appendFormat:@"%02x", result[i]]; |
| | | } |
| | | return hash; |
| | | } |
| | | |
| | | - (NSData *)sha384Data { |
| | | unsigned char result[CC_SHA384_DIGEST_LENGTH]; |
| | | CC_SHA384(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_SHA384_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)sha512String { |
| | | unsigned char result[CC_SHA512_DIGEST_LENGTH]; |
| | | CC_SHA512(self.bytes, (CC_LONG)self.length, result); |
| | | NSMutableString *hash = [NSMutableString |
| | | stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2]; |
| | | for (int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++) { |
| | | [hash appendFormat:@"%02x", result[i]]; |
| | | } |
| | | return hash; |
| | | } |
| | | |
| | | - (NSData *)sha512Data { |
| | | unsigned char result[CC_SHA512_DIGEST_LENGTH]; |
| | | CC_SHA512(self.bytes, (CC_LONG)self.length, result); |
| | | return [NSData dataWithBytes:result length:CC_SHA512_DIGEST_LENGTH]; |
| | | } |
| | | |
| | | - (NSString *)hmacStringUsingAlg:(CCHmacAlgorithm)alg withKey:(NSString *)key { |
| | | size_t size; |
| | | switch (alg) { |
| | | case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break; |
| | | default: return nil; |
| | | } |
| | | unsigned char result[size]; |
| | | const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; |
| | | CCHmac(alg, cKey, strlen(cKey), self.bytes, self.length, result); |
| | | NSMutableString *hash = [NSMutableString stringWithCapacity:size * 2]; |
| | | for (int i = 0; i < size; i++) { |
| | | [hash appendFormat:@"%02x", result[i]]; |
| | | } |
| | | return hash; |
| | | } |
| | | |
| | | - (NSData *)hmacDataUsingAlg:(CCHmacAlgorithm)alg withKey:(NSData *)key { |
| | | size_t size; |
| | | switch (alg) { |
| | | case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break; |
| | | case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break; |
| | | default: return nil; |
| | | } |
| | | unsigned char result[size]; |
| | | CCHmac(alg, [key bytes], key.length, self.bytes, self.length, result); |
| | | return [NSData dataWithBytes:result length:size]; |
| | | } |
| | | |
| | | - (NSString *)hmacMD5StringWithKey:(NSString *)key { |
| | | return [self hmacStringUsingAlg:kCCHmacAlgMD5 withKey:key]; |
| | | } |
| | | |
| | | - (NSData *)hmacMD5DataWithKey:(NSData *)key { |
| | | return [self hmacDataUsingAlg:kCCHmacAlgMD5 withKey:key]; |
| | | } |
| | | |
| | | - (NSString *)hmacSHA1StringWithKey:(NSString *)key { |
| | | return [self hmacStringUsingAlg:kCCHmacAlgSHA1 withKey:key]; |
| | | } |
| | | |
| | | - (NSData *)hmacSHA1DataWithKey:(NSData *)key { |
| | | return [self hmacDataUsingAlg:kCCHmacAlgSHA1 withKey:key]; |
| | | } |
| | | |
| | | - (NSString *)hmacSHA224StringWithKey:(NSString *)key { |
| | | return [self hmacStringUsingAlg:kCCHmacAlgSHA224 withKey:key]; |
| | | } |
| | | |
| | | - (NSData *)hmacSHA224DataWithKey:(NSData *)key { |
| | | return [self hmacDataUsingAlg:kCCHmacAlgSHA224 withKey:key]; |
| | | } |
| | | |
| | | - (NSString *)hmacSHA256StringWithKey:(NSString *)key { |
| | | return [self hmacStringUsingAlg:kCCHmacAlgSHA256 withKey:key]; |
| | | } |
| | | |
| | | - (NSData *)hmacSHA256DataWithKey:(NSData *)key { |
| | | return [self hmacDataUsingAlg:kCCHmacAlgSHA256 withKey:key]; |
| | | } |
| | | |
| | | - (NSString *)hmacSHA384StringWithKey:(NSString *)key { |
| | | return [self hmacStringUsingAlg:kCCHmacAlgSHA384 withKey:key]; |
| | | } |
| | | |
| | | - (NSData *)hmacSHA384DataWithKey:(NSData *)key { |
| | | return [self hmacDataUsingAlg:kCCHmacAlgSHA384 withKey:key]; |
| | | } |
| | | |
| | | - (NSString *)hmacSHA512StringWithKey:(NSString *)key { |
| | | return [self hmacStringUsingAlg:kCCHmacAlgSHA512 withKey:key]; |
| | | } |
| | | |
| | | - (NSData *)hmacSHA512DataWithKey:(NSData *)key { |
| | | return [self hmacDataUsingAlg:kCCHmacAlgSHA512 withKey:key]; |
| | | } |
| | | |
| | | - (NSString *)crc32String { |
| | | uLong result = crc32(0, self.bytes, (uInt)self.length); |
| | | return [NSString stringWithFormat:@"%08x", (uint32_t)result]; |
| | | } |
| | | |
| | | - (uint32_t)crc32 { |
| | | uLong result = crc32(0, self.bytes, (uInt)self.length); |
| | | return (uint32_t)result; |
| | | } |
| | | |
| | | - (NSData *)aes256EncryptWithKey:(NSData *)key iv:(NSData *)iv { |
| | | if (key.length != 16 && key.length != 24 && key.length != 32) { |
| | | return nil; |
| | | } |
| | | if (iv.length != 16 && iv.length != 0) { |
| | | return nil; |
| | | } |
| | | |
| | | NSData *result = nil; |
| | | size_t bufferSize = self.length + kCCBlockSizeAES128; |
| | | void *buffer = malloc(bufferSize); |
| | | if (!buffer) return nil; |
| | | size_t encryptedSize = 0; |
| | | CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, |
| | | kCCAlgorithmAES128, |
| | | kCCOptionPKCS7Padding, |
| | | key.bytes, |
| | | key.length, |
| | | iv.bytes, |
| | | self.bytes, |
| | | self.length, |
| | | buffer, |
| | | bufferSize, |
| | | &encryptedSize); |
| | | if (cryptStatus == kCCSuccess) { |
| | | result = [[NSData alloc]initWithBytes:buffer length:encryptedSize]; |
| | | free(buffer); |
| | | return result; |
| | | } else { |
| | | free(buffer); |
| | | return nil; |
| | | } |
| | | } |
| | | |
| | | - (NSData *)aes256DecryptWithkey:(NSData *)key iv:(NSData *)iv { |
| | | if (key.length != 16 && key.length != 24 && key.length != 32) { |
| | | return nil; |
| | | } |
| | | if (iv.length != 16 && iv.length != 0) { |
| | | return nil; |
| | | } |
| | | |
| | | NSData *result = nil; |
| | | size_t bufferSize = self.length + kCCBlockSizeAES128; |
| | | void *buffer = malloc(bufferSize); |
| | | if (!buffer) return nil; |
| | | size_t encryptedSize = 0; |
| | | CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, |
| | | kCCAlgorithmAES128, |
| | | kCCOptionPKCS7Padding, |
| | | key.bytes, |
| | | key.length, |
| | | iv.bytes, |
| | | self.bytes, |
| | | self.length, |
| | | buffer, |
| | | bufferSize, |
| | | &encryptedSize); |
| | | if (cryptStatus == kCCSuccess) { |
| | | result = [[NSData alloc]initWithBytes:buffer length:encryptedSize]; |
| | | free(buffer); |
| | | return result; |
| | | } else { |
| | | free(buffer); |
| | | return nil; |
| | | } |
| | | } |
| | | |
| | | - (NSString *)utf8String { |
| | | if (self.length > 0) { |
| | | return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding]; |
| | | } |
| | | return @""; |
| | | } |
| | | |
| | | - (NSString *)hexString { |
| | | NSUInteger length = self.length; |
| | | NSMutableString *result = [NSMutableString stringWithCapacity:length * 2]; |
| | | const unsigned char *byte = self.bytes; |
| | | for (int i = 0; i < length; i++, byte++) { |
| | | [result appendFormat:@"%02X", *byte]; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | + (NSData *)dataWithHexString:(NSString *)hexStr { |
| | | hexStr = [hexStr stringByReplacingOccurrencesOfString:@" " withString:@""]; |
| | | hexStr = [hexStr lowercaseString]; |
| | | NSUInteger len = hexStr.length; |
| | | if (!len) return nil; |
| | | unichar *buf = malloc(sizeof(unichar) * len); |
| | | if (!buf) return nil; |
| | | [hexStr getCharacters:buf range:NSMakeRange(0, len)]; |
| | | |
| | | NSMutableData *result = [NSMutableData data]; |
| | | unsigned char bytes; |
| | | char str[3] = { '\0', '\0', '\0' }; |
| | | int i; |
| | | for (i = 0; i < len / 2; i++) { |
| | | str[0] = buf[i * 2]; |
| | | str[1] = buf[i * 2 + 1]; |
| | | bytes = strtol(str, NULL, 16); |
| | | [result appendBytes:&bytes length:1]; |
| | | } |
| | | free(buf); |
| | | return result; |
| | | } |
| | | |
| | | static const char base64EncodingTable[64] |
| | | = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| | | static const short base64DecodingTable[256] = { |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63, |
| | | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2, |
| | | -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
| | | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2, |
| | | -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, |
| | | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, |
| | | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 |
| | | }; |
| | | |
| | | - (NSString *)base64EncodedString { |
| | | NSUInteger length = self.length; |
| | | if (length == 0) |
| | | return @""; |
| | | |
| | | NSUInteger out_length = ((length + 2) / 3) * 4; |
| | | uint8_t *output = malloc(((out_length + 2) / 3) * 4); |
| | | if (output == NULL) |
| | | return nil; |
| | | |
| | | const char *input = self.bytes; |
| | | NSInteger i, value; |
| | | for (i = 0; i < length; i += 3) { |
| | | value = 0; |
| | | for (NSInteger j = i; j < i + 3; j++) { |
| | | value <<= 8; |
| | | if (j < length) { |
| | | value |= (0xFF & input[j]); |
| | | } |
| | | } |
| | | NSInteger index = (i / 3) * 4; |
| | | output[index + 0] = base64EncodingTable[(value >> 18) & 0x3F]; |
| | | output[index + 1] = base64EncodingTable[(value >> 12) & 0x3F]; |
| | | output[index + 2] = ((i + 1) < length) |
| | | ? base64EncodingTable[(value >> 6) & 0x3F] |
| | | : '='; |
| | | output[index + 3] = ((i + 2) < length) |
| | | ? base64EncodingTable[(value >> 0) & 0x3F] |
| | | : '='; |
| | | } |
| | | |
| | | NSString *base64 = [[NSString alloc] initWithBytes:output |
| | | length:out_length |
| | | encoding:NSASCIIStringEncoding]; |
| | | free(output); |
| | | return base64; |
| | | } |
| | | |
| | | + (NSData *)dataWithBase64EncodedString:(NSString *)base64EncodedString { |
| | | NSInteger length = base64EncodedString.length; |
| | | const char *string = [base64EncodedString cStringUsingEncoding:NSASCIIStringEncoding]; |
| | | if (string == NULL) |
| | | return nil; |
| | | |
| | | while (length > 0 && string[length - 1] == '=') |
| | | length--; |
| | | |
| | | NSInteger outputLength = length * 3 / 4; |
| | | NSMutableData *data = [NSMutableData dataWithLength:outputLength]; |
| | | if (data == nil) |
| | | return nil; |
| | | if (length == 0) |
| | | return data; |
| | | |
| | | uint8_t *output = data.mutableBytes; |
| | | NSInteger inputPoint = 0; |
| | | NSInteger outputPoint = 0; |
| | | while (inputPoint < length) { |
| | | char i0 = string[inputPoint++]; |
| | | char i1 = string[inputPoint++]; |
| | | char i2 = inputPoint < length ? string[inputPoint++] : 'A'; |
| | | char i3 = inputPoint < length ? string[inputPoint++] : 'A'; |
| | | |
| | | output[outputPoint++] = (base64DecodingTable[i0] << 2) |
| | | | (base64DecodingTable[i1] >> 4); |
| | | if (outputPoint < outputLength) { |
| | | output[outputPoint++] = ((base64DecodingTable[i1] & 0xf) << 4) |
| | | | (base64DecodingTable[i2] >> 2); |
| | | } |
| | | if (outputPoint < outputLength) { |
| | | output[outputPoint++] = ((base64DecodingTable[i2] & 0x3) << 6) |
| | | | base64DecodingTable[i3]; |
| | | } |
| | | } |
| | | |
| | | return data; |
| | | } |
| | | |
| | | - (id)jsonValueDecoded { |
| | | NSError *error = nil; |
| | | id value = [NSJSONSerialization JSONObjectWithData:self options:kNilOptions error:&error]; |
| | | if (error) { |
| | | NSLog(@"jsonValueDecoded error:%@", error); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | - (NSData *)gzipInflate { |
| | | if ([self length] == 0) return self; |
| | | |
| | | unsigned full_length = (unsigned)[self length]; |
| | | unsigned half_length = (unsigned)[self length] / 2; |
| | | |
| | | NSMutableData *decompressed = [NSMutableData |
| | | dataWithLength:full_length + half_length]; |
| | | BOOL done = NO; |
| | | int status; |
| | | |
| | | z_stream strm; |
| | | strm.next_in = (Bytef *)[self bytes]; |
| | | strm.avail_in = (unsigned)[self length]; |
| | | strm.total_out = 0; |
| | | strm.zalloc = Z_NULL; |
| | | strm.zfree = Z_NULL; |
| | | |
| | | if (inflateInit2(&strm, (15 + 32)) != Z_OK) return nil; |
| | | while (!done) { |
| | | // Make sure we have enough room and reset the lengths. |
| | | if (strm.total_out >= [decompressed length]) |
| | | [decompressed increaseLengthBy:half_length]; |
| | | strm.next_out = [decompressed mutableBytes] + strm.total_out; |
| | | strm.avail_out = (uInt)([decompressed length] - strm.total_out); |
| | | |
| | | // Inflate another chunk. |
| | | status = inflate(&strm, Z_SYNC_FLUSH); |
| | | if (status == Z_STREAM_END) done = YES; |
| | | else if (status != Z_OK) break; |
| | | } |
| | | if (inflateEnd(&strm) != Z_OK) return nil; |
| | | |
| | | // Set real length. |
| | | if (done) { |
| | | [decompressed setLength:strm.total_out]; |
| | | return [NSData dataWithData:decompressed]; |
| | | } else return nil; |
| | | } |
| | | |
| | | - (NSData *)gzipDeflate { |
| | | if ([self length] == 0) return self; |
| | | |
| | | z_stream strm; |
| | | |
| | | strm.zalloc = Z_NULL; |
| | | strm.zfree = Z_NULL; |
| | | strm.opaque = Z_NULL; |
| | | strm.total_out = 0; |
| | | strm.next_in = (Bytef *)[self bytes]; |
| | | strm.avail_in = (uInt)[self length]; |
| | | |
| | | // Compresssion Levels: |
| | | // Z_NO_COMPRESSION |
| | | // Z_BEST_SPEED |
| | | // Z_BEST_COMPRESSION |
| | | // Z_DEFAULT_COMPRESSION |
| | | |
| | | if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15 + 16), |
| | | 8, Z_DEFAULT_STRATEGY) != Z_OK) |
| | | return nil; |
| | | |
| | | // 16K chunks for expansion |
| | | NSMutableData *compressed = [NSMutableData dataWithLength:16384]; |
| | | |
| | | do { |
| | | if (strm.total_out >= [compressed length]) |
| | | [compressed increaseLengthBy:16384]; |
| | | |
| | | strm.next_out = [compressed mutableBytes] + strm.total_out; |
| | | strm.avail_out = (uInt)([compressed length] - strm.total_out); |
| | | |
| | | deflate(&strm, Z_FINISH); |
| | | } |
| | | while (strm.avail_out == 0); |
| | | |
| | | deflateEnd(&strm); |
| | | |
| | | [compressed setLength:strm.total_out]; |
| | | return [NSData dataWithData:compressed]; |
| | | } |
| | | |
| | | - (NSData *)zlibInflate { |
| | | if ([self length] == 0) return self; |
| | | |
| | | NSUInteger full_length = [self length]; |
| | | NSUInteger half_length = [self length] / 2; |
| | | |
| | | NSMutableData *decompressed = [NSMutableData |
| | | dataWithLength:full_length + half_length]; |
| | | BOOL done = NO; |
| | | int status; |
| | | |
| | | z_stream strm; |
| | | strm.next_in = (Bytef *)[self bytes]; |
| | | strm.avail_in = (uInt)full_length; |
| | | strm.total_out = 0; |
| | | strm.zalloc = Z_NULL; |
| | | strm.zfree = Z_NULL; |
| | | |
| | | if (inflateInit(&strm) != Z_OK) return nil; |
| | | |
| | | while (!done) { |
| | | // Make sure we have enough room and reset the lengths. |
| | | if (strm.total_out >= [decompressed length]) |
| | | [decompressed increaseLengthBy:half_length]; |
| | | strm.next_out = [decompressed mutableBytes] + strm.total_out; |
| | | strm.avail_out = (uInt)([decompressed length] - strm.total_out); |
| | | |
| | | // Inflate another chunk. |
| | | status = inflate(&strm, Z_SYNC_FLUSH); |
| | | if (status == Z_STREAM_END) done = YES; |
| | | else if (status != Z_OK) break; |
| | | } |
| | | if (inflateEnd(&strm) != Z_OK) return nil; |
| | | |
| | | // Set real length. |
| | | if (done) { |
| | | [decompressed setLength:strm.total_out]; |
| | | return [NSData dataWithData:decompressed]; |
| | | } else return nil; |
| | | } |
| | | |
| | | - (NSData *)zlibDeflate { |
| | | if ([self length] == 0) return self; |
| | | |
| | | z_stream strm; |
| | | |
| | | strm.zalloc = Z_NULL; |
| | | strm.zfree = Z_NULL; |
| | | strm.opaque = Z_NULL; |
| | | strm.total_out = 0; |
| | | strm.next_in = (Bytef *)[self bytes]; |
| | | strm.avail_in = (uInt)[self length]; |
| | | |
| | | // Compresssion Levels: |
| | | // Z_NO_COMPRESSION |
| | | // Z_BEST_SPEED |
| | | // Z_BEST_COMPRESSION |
| | | // Z_DEFAULT_COMPRESSION |
| | | |
| | | if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) != Z_OK) return nil; |
| | | |
| | | // 16K chuncks for expansion |
| | | NSMutableData *compressed = [NSMutableData dataWithLength:16384]; |
| | | |
| | | do { |
| | | if (strm.total_out >= [compressed length]) |
| | | [compressed increaseLengthBy:16384]; |
| | | |
| | | strm.next_out = [compressed mutableBytes] + strm.total_out; |
| | | strm.avail_out = (uInt)([compressed length] - strm.total_out); |
| | | |
| | | deflate(&strm, Z_FINISH); |
| | | } |
| | | while (strm.avail_out == 0); |
| | | |
| | | deflateEnd(&strm); |
| | | |
| | | [compressed setLength:strm.total_out]; |
| | | return [NSData dataWithData:compressed]; |
| | | } |
| | | |
| | | + (NSData *)dataNamed:(NSString *)name { |
| | | NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@""]; |
| | | if (!path) return nil; |
| | | NSData *data = [NSData dataWithContentsOfFile:path]; |
| | | return data; |
| | | } |
| | | |
| | | @end |