NSData+CocoaDevAdditions.m 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. //
  2. // NSData+CocoaDevAdditions.m
  3. // InsideJob
  4. //
  5. // Created by Adam Preble on 10/6/10.
  6. //
  7. // Source: http://www.cocoadev.com/index.pl?NSDataCategory
  8. #import "NSData+CocoaDevAdditions.h"
  9. #import <zlib.h>
  10. @implementation NSData (CocoaDevAdditions)
  11. - (NSData *)gzipInflate
  12. {
  13. if ([self length] == 0) return self;
  14. unsigned full_length = [self length];
  15. unsigned half_length = [self length] / 2;
  16. NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
  17. BOOL done = NO;
  18. int status;
  19. z_stream strm;
  20. strm.next_in = (Bytef *)[self bytes];
  21. strm.avail_in = [self length];
  22. strm.total_out = 0;
  23. strm.zalloc = Z_NULL;
  24. strm.zfree = Z_NULL;
  25. if (inflateInit2(&strm, (15+32)) != Z_OK) return nil;
  26. while (!done)
  27. {
  28. // Make sure we have enough room and reset the lengths.
  29. if (strm.total_out >= [decompressed length])
  30. [decompressed increaseLengthBy: half_length];
  31. strm.next_out = [decompressed mutableBytes] + strm.total_out;
  32. strm.avail_out = [decompressed length] - strm.total_out;
  33. // Inflate another chunk.
  34. status = inflate (&strm, Z_SYNC_FLUSH);
  35. if (status == Z_STREAM_END) done = YES;
  36. else if (status != Z_OK) break;
  37. }
  38. if (inflateEnd (&strm) != Z_OK) return nil;
  39. // Set real length.
  40. if (done)
  41. {
  42. [decompressed setLength: strm.total_out];
  43. return [NSData dataWithData: decompressed];
  44. }
  45. else return nil;
  46. }
  47. - (NSData *)gzipDeflate
  48. {
  49. if ([self length] == 0) return self;
  50. z_stream strm;
  51. strm.zalloc = Z_NULL;
  52. strm.zfree = Z_NULL;
  53. strm.opaque = Z_NULL;
  54. strm.total_out = 0;
  55. strm.next_in=(Bytef *)[self bytes];
  56. strm.avail_in = [self length];
  57. // Compresssion Levels:
  58. // Z_NO_COMPRESSION
  59. // Z_BEST_SPEED
  60. // Z_BEST_COMPRESSION
  61. // Z_DEFAULT_COMPRESSION
  62. if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil;
  63. NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion
  64. do {
  65. if (strm.total_out >= [compressed length])
  66. [compressed increaseLengthBy: 16384];
  67. strm.next_out = [compressed mutableBytes] + strm.total_out;
  68. strm.avail_out = [compressed length] - strm.total_out;
  69. deflate(&strm, Z_FINISH);
  70. } while (strm.avail_out == 0);
  71. deflateEnd(&strm);
  72. [compressed setLength: strm.total_out];
  73. return [NSData dataWithData:compressed];
  74. }
  75. @end