NSData+YYAdd.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. //
  2. // NSData+YYAdd.m
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 13/4/4.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import "NSData+YYAdd.h"
  12. #import "YYKitMacro.h"
  13. #include <CommonCrypto/CommonCrypto.h>
  14. #include <zlib.h>
  15. YYSYNTH_DUMMY_CLASS(NSData_YYAdd)
  16. @implementation NSData (YYAdd)
  17. - (NSString *)md2String {
  18. unsigned char result[CC_MD2_DIGEST_LENGTH];
  19. CC_MD2(self.bytes, (CC_LONG)self.length, result);
  20. return [NSString stringWithFormat:
  21. @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  22. result[0], result[1], result[2], result[3],
  23. result[4], result[5], result[6], result[7],
  24. result[8], result[9], result[10], result[11],
  25. result[12], result[13], result[14], result[15]
  26. ];
  27. }
  28. - (NSData *)md2Data {
  29. unsigned char result[CC_MD2_DIGEST_LENGTH];
  30. CC_MD2(self.bytes, (CC_LONG)self.length, result);
  31. return [NSData dataWithBytes:result length:CC_MD2_DIGEST_LENGTH];
  32. }
  33. - (NSString *)md4String {
  34. unsigned char result[CC_MD4_DIGEST_LENGTH];
  35. CC_MD4(self.bytes, (CC_LONG)self.length, result);
  36. return [NSString stringWithFormat:
  37. @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  38. result[0], result[1], result[2], result[3],
  39. result[4], result[5], result[6], result[7],
  40. result[8], result[9], result[10], result[11],
  41. result[12], result[13], result[14], result[15]
  42. ];
  43. }
  44. - (NSData *)md4Data {
  45. unsigned char result[CC_MD4_DIGEST_LENGTH];
  46. CC_MD4(self.bytes, (CC_LONG)self.length, result);
  47. return [NSData dataWithBytes:result length:CC_MD4_DIGEST_LENGTH];
  48. }
  49. - (NSString *)md5String {
  50. unsigned char result[CC_MD5_DIGEST_LENGTH];
  51. CC_MD5(self.bytes, (CC_LONG)self.length, result);
  52. return [NSString stringWithFormat:
  53. @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  54. result[0], result[1], result[2], result[3],
  55. result[4], result[5], result[6], result[7],
  56. result[8], result[9], result[10], result[11],
  57. result[12], result[13], result[14], result[15]
  58. ];
  59. }
  60. - (NSData *)md5Data {
  61. unsigned char result[CC_MD5_DIGEST_LENGTH];
  62. CC_MD5(self.bytes, (CC_LONG)self.length, result);
  63. return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];
  64. }
  65. - (NSString *)sha1String {
  66. unsigned char result[CC_SHA1_DIGEST_LENGTH];
  67. CC_SHA1(self.bytes, (CC_LONG)self.length, result);
  68. NSMutableString *hash = [NSMutableString
  69. stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
  70. for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
  71. [hash appendFormat:@"%02x", result[i]];
  72. }
  73. return hash;
  74. }
  75. - (NSData *)sha1Data {
  76. unsigned char result[CC_SHA1_DIGEST_LENGTH];
  77. CC_SHA1(self.bytes, (CC_LONG)self.length, result);
  78. return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH];
  79. }
  80. - (NSString *)sha224String {
  81. unsigned char result[CC_SHA224_DIGEST_LENGTH];
  82. CC_SHA224(self.bytes, (CC_LONG)self.length, result);
  83. NSMutableString *hash = [NSMutableString
  84. stringWithCapacity:CC_SHA224_DIGEST_LENGTH * 2];
  85. for (int i = 0; i < CC_SHA224_DIGEST_LENGTH; i++) {
  86. [hash appendFormat:@"%02x", result[i]];
  87. }
  88. return hash;
  89. }
  90. - (NSData *)sha224Data {
  91. unsigned char result[CC_SHA224_DIGEST_LENGTH];
  92. CC_SHA224(self.bytes, (CC_LONG)self.length, result);
  93. return [NSData dataWithBytes:result length:CC_SHA224_DIGEST_LENGTH];
  94. }
  95. - (NSString *)sha256String {
  96. unsigned char result[CC_SHA256_DIGEST_LENGTH];
  97. CC_SHA256(self.bytes, (CC_LONG)self.length, result);
  98. NSMutableString *hash = [NSMutableString
  99. stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
  100. for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
  101. [hash appendFormat:@"%02x", result[i]];
  102. }
  103. return hash;
  104. }
  105. - (NSData *)sha256Data {
  106. unsigned char result[CC_SHA256_DIGEST_LENGTH];
  107. CC_SHA256(self.bytes, (CC_LONG)self.length, result);
  108. return [NSData dataWithBytes:result length:CC_SHA256_DIGEST_LENGTH];
  109. }
  110. - (NSString *)sha384String {
  111. unsigned char result[CC_SHA384_DIGEST_LENGTH];
  112. CC_SHA384(self.bytes, (CC_LONG)self.length, result);
  113. NSMutableString *hash = [NSMutableString
  114. stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
  115. for (int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++) {
  116. [hash appendFormat:@"%02x", result[i]];
  117. }
  118. return hash;
  119. }
  120. - (NSData *)sha384Data {
  121. unsigned char result[CC_SHA384_DIGEST_LENGTH];
  122. CC_SHA384(self.bytes, (CC_LONG)self.length, result);
  123. return [NSData dataWithBytes:result length:CC_SHA384_DIGEST_LENGTH];
  124. }
  125. - (NSString *)sha512String {
  126. unsigned char result[CC_SHA512_DIGEST_LENGTH];
  127. CC_SHA512(self.bytes, (CC_LONG)self.length, result);
  128. NSMutableString *hash = [NSMutableString
  129. stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
  130. for (int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++) {
  131. [hash appendFormat:@"%02x", result[i]];
  132. }
  133. return hash;
  134. }
  135. - (NSData *)sha512Data {
  136. unsigned char result[CC_SHA512_DIGEST_LENGTH];
  137. CC_SHA512(self.bytes, (CC_LONG)self.length, result);
  138. return [NSData dataWithBytes:result length:CC_SHA512_DIGEST_LENGTH];
  139. }
  140. - (NSString *)hmacStringUsingAlg:(CCHmacAlgorithm)alg withKey:(NSString *)key {
  141. size_t size;
  142. switch (alg) {
  143. case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break;
  144. case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break;
  145. case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break;
  146. case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break;
  147. case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break;
  148. case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break;
  149. default: return nil;
  150. }
  151. unsigned char result[size];
  152. const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
  153. CCHmac(alg, cKey, strlen(cKey), self.bytes, self.length, result);
  154. NSMutableString *hash = [NSMutableString stringWithCapacity:size * 2];
  155. for (int i = 0; i < size; i++) {
  156. [hash appendFormat:@"%02x", result[i]];
  157. }
  158. return hash;
  159. }
  160. - (NSData *)hmacDataUsingAlg:(CCHmacAlgorithm)alg withKey:(NSData *)key {
  161. size_t size;
  162. switch (alg) {
  163. case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break;
  164. case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break;
  165. case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break;
  166. case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break;
  167. case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break;
  168. case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break;
  169. default: return nil;
  170. }
  171. unsigned char result[size];
  172. CCHmac(alg, [key bytes], key.length, self.bytes, self.length, result);
  173. return [NSData dataWithBytes:result length:size];
  174. }
  175. - (NSString *)hmacMD5StringWithKey:(NSString *)key {
  176. return [self hmacStringUsingAlg:kCCHmacAlgMD5 withKey:key];
  177. }
  178. - (NSData *)hmacMD5DataWithKey:(NSData *)key {
  179. return [self hmacDataUsingAlg:kCCHmacAlgMD5 withKey:key];
  180. }
  181. - (NSString *)hmacSHA1StringWithKey:(NSString *)key {
  182. return [self hmacStringUsingAlg:kCCHmacAlgSHA1 withKey:key];
  183. }
  184. - (NSData *)hmacSHA1DataWithKey:(NSData *)key {
  185. return [self hmacDataUsingAlg:kCCHmacAlgSHA1 withKey:key];
  186. }
  187. - (NSString *)hmacSHA224StringWithKey:(NSString *)key {
  188. return [self hmacStringUsingAlg:kCCHmacAlgSHA224 withKey:key];
  189. }
  190. - (NSData *)hmacSHA224DataWithKey:(NSData *)key {
  191. return [self hmacDataUsingAlg:kCCHmacAlgSHA224 withKey:key];
  192. }
  193. - (NSString *)hmacSHA256StringWithKey:(NSString *)key {
  194. return [self hmacStringUsingAlg:kCCHmacAlgSHA256 withKey:key];
  195. }
  196. - (NSData *)hmacSHA256DataWithKey:(NSData *)key {
  197. return [self hmacDataUsingAlg:kCCHmacAlgSHA256 withKey:key];
  198. }
  199. - (NSString *)hmacSHA384StringWithKey:(NSString *)key {
  200. return [self hmacStringUsingAlg:kCCHmacAlgSHA384 withKey:key];
  201. }
  202. - (NSData *)hmacSHA384DataWithKey:(NSData *)key {
  203. return [self hmacDataUsingAlg:kCCHmacAlgSHA384 withKey:key];
  204. }
  205. - (NSString *)hmacSHA512StringWithKey:(NSString *)key {
  206. return [self hmacStringUsingAlg:kCCHmacAlgSHA512 withKey:key];
  207. }
  208. - (NSData *)hmacSHA512DataWithKey:(NSData *)key {
  209. return [self hmacDataUsingAlg:kCCHmacAlgSHA512 withKey:key];
  210. }
  211. - (NSString *)crc32String {
  212. uLong result = crc32(0, self.bytes, (uInt)self.length);
  213. return [NSString stringWithFormat:@"%08x", (uint32_t)result];
  214. }
  215. - (uint32_t)crc32 {
  216. uLong result = crc32(0, self.bytes, (uInt)self.length);
  217. return (uint32_t)result;
  218. }
  219. - (NSData *)aes256EncryptWithKey:(NSData *)key iv:(NSData *)iv {
  220. if (key.length != 16 && key.length != 24 && key.length != 32) {
  221. return nil;
  222. }
  223. if (iv.length != 16 && iv.length != 0) {
  224. return nil;
  225. }
  226. NSData *result = nil;
  227. size_t bufferSize = self.length + kCCBlockSizeAES128;
  228. void *buffer = malloc(bufferSize);
  229. if (!buffer) return nil;
  230. size_t encryptedSize = 0;
  231. CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
  232. kCCAlgorithmAES128,
  233. kCCOptionPKCS7Padding,
  234. key.bytes,
  235. key.length,
  236. iv.bytes,
  237. self.bytes,
  238. self.length,
  239. buffer,
  240. bufferSize,
  241. &encryptedSize);
  242. if (cryptStatus == kCCSuccess) {
  243. result = [[NSData alloc]initWithBytes:buffer length:encryptedSize];
  244. free(buffer);
  245. return result;
  246. } else {
  247. free(buffer);
  248. return nil;
  249. }
  250. }
  251. - (NSData *)aes256DecryptWithkey:(NSData *)key iv:(NSData *)iv {
  252. if (key.length != 16 && key.length != 24 && key.length != 32) {
  253. return nil;
  254. }
  255. if (iv.length != 16 && iv.length != 0) {
  256. return nil;
  257. }
  258. NSData *result = nil;
  259. size_t bufferSize = self.length + kCCBlockSizeAES128;
  260. void *buffer = malloc(bufferSize);
  261. if (!buffer) return nil;
  262. size_t encryptedSize = 0;
  263. CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
  264. kCCAlgorithmAES128,
  265. kCCOptionPKCS7Padding,
  266. key.bytes,
  267. key.length,
  268. iv.bytes,
  269. self.bytes,
  270. self.length,
  271. buffer,
  272. bufferSize,
  273. &encryptedSize);
  274. if (cryptStatus == kCCSuccess) {
  275. result = [[NSData alloc]initWithBytes:buffer length:encryptedSize];
  276. free(buffer);
  277. return result;
  278. } else {
  279. free(buffer);
  280. return nil;
  281. }
  282. }
  283. - (NSString *)utf8String {
  284. if (self.length > 0) {
  285. return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
  286. }
  287. return @"";
  288. }
  289. - (NSString *)hexString {
  290. NSUInteger length = self.length;
  291. NSMutableString *result = [NSMutableString stringWithCapacity:length * 2];
  292. const unsigned char *byte = self.bytes;
  293. for (int i = 0; i < length; i++, byte++) {
  294. [result appendFormat:@"%02X", *byte];
  295. }
  296. return result;
  297. }
  298. + (NSData *)dataWithHexString:(NSString *)hexStr {
  299. hexStr = [hexStr stringByReplacingOccurrencesOfString:@" " withString:@""];
  300. hexStr = [hexStr lowercaseString];
  301. NSUInteger len = hexStr.length;
  302. if (!len) return nil;
  303. unichar *buf = malloc(sizeof(unichar) * len);
  304. if (!buf) return nil;
  305. [hexStr getCharacters:buf range:NSMakeRange(0, len)];
  306. NSMutableData *result = [NSMutableData data];
  307. unsigned char bytes;
  308. char str[3] = { '\0', '\0', '\0' };
  309. int i;
  310. for (i = 0; i < len / 2; i++) {
  311. str[0] = buf[i * 2];
  312. str[1] = buf[i * 2 + 1];
  313. bytes = strtol(str, NULL, 16);
  314. [result appendBytes:&bytes length:1];
  315. }
  316. free(buf);
  317. return result;
  318. }
  319. static const char base64EncodingTable[64]
  320. = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  321. static const short base64DecodingTable[256] = {
  322. -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2,
  323. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  324. -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
  325. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
  326. -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  327. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
  328. -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  329. 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
  330. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  331. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  332. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  333. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  334. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  335. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  336. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
  337. -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
  338. };
  339. - (NSString *)base64EncodedString {
  340. NSUInteger length = self.length;
  341. if (length == 0)
  342. return @"";
  343. NSUInteger out_length = ((length + 2) / 3) * 4;
  344. uint8_t *output = malloc(((out_length + 2) / 3) * 4);
  345. if (output == NULL)
  346. return nil;
  347. const char *input = self.bytes;
  348. NSInteger i, value;
  349. for (i = 0; i < length; i += 3) {
  350. value = 0;
  351. for (NSInteger j = i; j < i + 3; j++) {
  352. value <<= 8;
  353. if (j < length) {
  354. value |= (0xFF & input[j]);
  355. }
  356. }
  357. NSInteger index = (i / 3) * 4;
  358. output[index + 0] = base64EncodingTable[(value >> 18) & 0x3F];
  359. output[index + 1] = base64EncodingTable[(value >> 12) & 0x3F];
  360. output[index + 2] = ((i + 1) < length)
  361. ? base64EncodingTable[(value >> 6) & 0x3F]
  362. : '=';
  363. output[index + 3] = ((i + 2) < length)
  364. ? base64EncodingTable[(value >> 0) & 0x3F]
  365. : '=';
  366. }
  367. NSString *base64 = [[NSString alloc] initWithBytes:output
  368. length:out_length
  369. encoding:NSASCIIStringEncoding];
  370. free(output);
  371. return base64;
  372. }
  373. + (NSData *)dataWithBase64EncodedString:(NSString *)base64EncodedString {
  374. NSInteger length = base64EncodedString.length;
  375. const char *string = [base64EncodedString cStringUsingEncoding:NSASCIIStringEncoding];
  376. if (string == NULL)
  377. return nil;
  378. while (length > 0 && string[length - 1] == '=')
  379. length--;
  380. NSInteger outputLength = length * 3 / 4;
  381. NSMutableData *data = [NSMutableData dataWithLength:outputLength];
  382. if (data == nil)
  383. return nil;
  384. if (length == 0)
  385. return data;
  386. uint8_t *output = data.mutableBytes;
  387. NSInteger inputPoint = 0;
  388. NSInteger outputPoint = 0;
  389. while (inputPoint < length) {
  390. char i0 = string[inputPoint++];
  391. char i1 = string[inputPoint++];
  392. char i2 = inputPoint < length ? string[inputPoint++] : 'A';
  393. char i3 = inputPoint < length ? string[inputPoint++] : 'A';
  394. output[outputPoint++] = (base64DecodingTable[i0] << 2)
  395. | (base64DecodingTable[i1] >> 4);
  396. if (outputPoint < outputLength) {
  397. output[outputPoint++] = ((base64DecodingTable[i1] & 0xf) << 4)
  398. | (base64DecodingTable[i2] >> 2);
  399. }
  400. if (outputPoint < outputLength) {
  401. output[outputPoint++] = ((base64DecodingTable[i2] & 0x3) << 6)
  402. | base64DecodingTable[i3];
  403. }
  404. }
  405. return data;
  406. }
  407. - (id)jsonValueDecoded {
  408. NSError *error = nil;
  409. id value = [NSJSONSerialization JSONObjectWithData:self options:kNilOptions error:&error];
  410. if (error) {
  411. NSLog(@"jsonValueDecoded error:%@", error);
  412. }
  413. return value;
  414. }
  415. - (NSData *)gzipInflate {
  416. if ([self length] == 0) return self;
  417. unsigned full_length = (unsigned)[self length];
  418. unsigned half_length = (unsigned)[self length] / 2;
  419. NSMutableData *decompressed = [NSMutableData
  420. dataWithLength:full_length + half_length];
  421. BOOL done = NO;
  422. int status;
  423. z_stream strm;
  424. strm.next_in = (Bytef *)[self bytes];
  425. strm.avail_in = (unsigned)[self length];
  426. strm.total_out = 0;
  427. strm.zalloc = Z_NULL;
  428. strm.zfree = Z_NULL;
  429. if (inflateInit2(&strm, (15 + 32)) != Z_OK) return nil;
  430. while (!done) {
  431. // Make sure we have enough room and reset the lengths.
  432. if (strm.total_out >= [decompressed length])
  433. [decompressed increaseLengthBy:half_length];
  434. strm.next_out = [decompressed mutableBytes] + strm.total_out;
  435. strm.avail_out = (uInt)([decompressed length] - strm.total_out);
  436. // Inflate another chunk.
  437. status = inflate(&strm, Z_SYNC_FLUSH);
  438. if (status == Z_STREAM_END) done = YES;
  439. else if (status != Z_OK) break;
  440. }
  441. if (inflateEnd(&strm) != Z_OK) return nil;
  442. // Set real length.
  443. if (done) {
  444. [decompressed setLength:strm.total_out];
  445. return [NSData dataWithData:decompressed];
  446. } else return nil;
  447. }
  448. - (NSData *)gzipDeflate {
  449. if ([self length] == 0) return self;
  450. z_stream strm;
  451. strm.zalloc = Z_NULL;
  452. strm.zfree = Z_NULL;
  453. strm.opaque = Z_NULL;
  454. strm.total_out = 0;
  455. strm.next_in = (Bytef *)[self bytes];
  456. strm.avail_in = (uInt)[self length];
  457. // Compresssion Levels:
  458. // Z_NO_COMPRESSION
  459. // Z_BEST_SPEED
  460. // Z_BEST_COMPRESSION
  461. // Z_DEFAULT_COMPRESSION
  462. if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15 + 16),
  463. 8, Z_DEFAULT_STRATEGY) != Z_OK)
  464. return nil;
  465. // 16K chunks for expansion
  466. NSMutableData *compressed = [NSMutableData dataWithLength:16384];
  467. do {
  468. if (strm.total_out >= [compressed length])
  469. [compressed increaseLengthBy:16384];
  470. strm.next_out = [compressed mutableBytes] + strm.total_out;
  471. strm.avail_out = (uInt)([compressed length] - strm.total_out);
  472. deflate(&strm, Z_FINISH);
  473. }
  474. while (strm.avail_out == 0);
  475. deflateEnd(&strm);
  476. [compressed setLength:strm.total_out];
  477. return [NSData dataWithData:compressed];
  478. }
  479. - (NSData *)zlibInflate {
  480. if ([self length] == 0) return self;
  481. NSUInteger full_length = [self length];
  482. NSUInteger half_length = [self length] / 2;
  483. NSMutableData *decompressed = [NSMutableData
  484. dataWithLength:full_length + half_length];
  485. BOOL done = NO;
  486. int status;
  487. z_stream strm;
  488. strm.next_in = (Bytef *)[self bytes];
  489. strm.avail_in = (uInt)full_length;
  490. strm.total_out = 0;
  491. strm.zalloc = Z_NULL;
  492. strm.zfree = Z_NULL;
  493. if (inflateInit(&strm) != Z_OK) return nil;
  494. while (!done) {
  495. // Make sure we have enough room and reset the lengths.
  496. if (strm.total_out >= [decompressed length])
  497. [decompressed increaseLengthBy:half_length];
  498. strm.next_out = [decompressed mutableBytes] + strm.total_out;
  499. strm.avail_out = (uInt)([decompressed length] - strm.total_out);
  500. // Inflate another chunk.
  501. status = inflate(&strm, Z_SYNC_FLUSH);
  502. if (status == Z_STREAM_END) done = YES;
  503. else if (status != Z_OK) break;
  504. }
  505. if (inflateEnd(&strm) != Z_OK) return nil;
  506. // Set real length.
  507. if (done) {
  508. [decompressed setLength:strm.total_out];
  509. return [NSData dataWithData:decompressed];
  510. } else return nil;
  511. }
  512. - (NSData *)zlibDeflate {
  513. if ([self length] == 0) return self;
  514. z_stream strm;
  515. strm.zalloc = Z_NULL;
  516. strm.zfree = Z_NULL;
  517. strm.opaque = Z_NULL;
  518. strm.total_out = 0;
  519. strm.next_in = (Bytef *)[self bytes];
  520. strm.avail_in = (uInt)[self length];
  521. // Compresssion Levels:
  522. // Z_NO_COMPRESSION
  523. // Z_BEST_SPEED
  524. // Z_BEST_COMPRESSION
  525. // Z_DEFAULT_COMPRESSION
  526. if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) != Z_OK) return nil;
  527. // 16K chuncks for expansion
  528. NSMutableData *compressed = [NSMutableData dataWithLength:16384];
  529. do {
  530. if (strm.total_out >= [compressed length])
  531. [compressed increaseLengthBy:16384];
  532. strm.next_out = [compressed mutableBytes] + strm.total_out;
  533. strm.avail_out = (uInt)([compressed length] - strm.total_out);
  534. deflate(&strm, Z_FINISH);
  535. }
  536. while (strm.avail_out == 0);
  537. deflateEnd(&strm);
  538. [compressed setLength:strm.total_out];
  539. return [NSData dataWithData:compressed];
  540. }
  541. + (NSData *)dataNamed:(NSString *)name {
  542. NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@""];
  543. if (!path) return nil;
  544. NSData *data = [NSData dataWithContentsOfFile:path];
  545. return data;
  546. }
  547. @end