NSData+QNGZip.m 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //
  2. // NSData+QNGZip.m
  3. // GZipTest
  4. //
  5. // Created by yangsen on 2020/8/12.
  6. // Copyright © 2020 yangsen. All rights reserved.
  7. //
  8. #import "NSData+QNGZip.h"
  9. #import <zlib.h>
  10. #pragma clang diagnostic ignored "-Wcast-qual"
  11. @implementation NSData(QNGZip)
  12. + (NSData *)qn_gZip:(NSData *)data{
  13. if (data.length == 0 || [self qn_isGzippedData:data]){
  14. return data;
  15. }
  16. z_stream stream;
  17. stream.opaque = Z_NULL;
  18. stream.zalloc = Z_NULL;
  19. stream.zfree = Z_NULL;
  20. stream.total_out = 0;
  21. stream.avail_out = 0;
  22. stream.avail_in = (uint)data.length;
  23. stream.next_in = (Bytef *)(void *)data.bytes;
  24. static const NSUInteger chunkSize = 16384;
  25. NSMutableData *gzippedData = nil;
  26. if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) == Z_OK) {
  27. gzippedData = [NSMutableData dataWithLength:chunkSize];
  28. while (stream.avail_out == 0) {
  29. if (stream.total_out >= gzippedData.length) {
  30. gzippedData.length += chunkSize;
  31. }
  32. stream.next_out = (uint8_t *)gzippedData.mutableBytes + stream.total_out;
  33. stream.avail_out = (uInt)(gzippedData.length - stream.total_out);
  34. deflate(&stream, Z_FINISH);
  35. }
  36. deflateEnd(&stream);
  37. gzippedData.length = stream.total_out;
  38. }
  39. return gzippedData;
  40. }
  41. + (NSData *)qn_gUnzip:(NSData *)data{
  42. if (data.length == 0 || ![self qn_isGzippedData:data]){
  43. return data;
  44. }
  45. z_stream stream;
  46. stream.zalloc = Z_NULL;
  47. stream.zfree = Z_NULL;
  48. stream.total_out = 0;
  49. stream.avail_out = 0;
  50. stream.avail_in = (uint)data.length;
  51. stream.next_in = (Bytef *)data.bytes;
  52. NSMutableData *gunzippedData = nil;
  53. if (inflateInit2(&stream, 47) == Z_OK) {
  54. int status = Z_OK;
  55. gunzippedData = [NSMutableData dataWithCapacity:data.length * 2];
  56. while (status == Z_OK) {
  57. if (stream.total_out >= gunzippedData.length) {
  58. gunzippedData.length += data.length / 2;
  59. }
  60. stream.next_out = (uint8_t *)gunzippedData.mutableBytes + stream.total_out;
  61. stream.avail_out = (uInt)(gunzippedData.length - stream.total_out);
  62. status = inflate (&stream, Z_SYNC_FLUSH);
  63. }
  64. if (inflateEnd(&stream) == Z_OK) {
  65. if (status == Z_STREAM_END) {
  66. gunzippedData.length = stream.total_out;
  67. }
  68. }
  69. }
  70. return gunzippedData;
  71. }
  72. + (BOOL)qn_isGzippedData:(NSData *)data{
  73. if (!data || data.length == 0) {
  74. return false;
  75. }
  76. const UInt8 *bytes = (const UInt8 *)data.bytes;
  77. return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
  78. }
  79. @end