123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642 |
- //
- // NSData+YYAdd.m
- // YYKit <https://github.com/ibireme/YYKit>
- //
- // 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 "YYKitMacro.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
|