Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/*
2
 * Copyright 2020 Google LLC
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h"
18
 
19
#import <zlib.h>
20
 
21
@implementation GDTCCTCompressionHelper
22
 
23
+ (nullable NSData *)gzippedData:(NSData *)data {
24
#if defined(__LP64__) && __LP64__
25
  // Don't support > 32bit length for 64 bit, see note in header.
26
  if (data.length > UINT_MAX) {
27
    return nil;
28
  }
29
#endif
30
 
31
  enum { kChunkSize = 1024 };
32
 
33
  const void *bytes = [data bytes];
34
  NSUInteger length = [data length];
35
 
36
  int level = Z_DEFAULT_COMPRESSION;
37
  if (!bytes || !length) {
38
    return nil;
39
  }
40
 
41
  z_stream strm;
42
  bzero(&strm, sizeof(z_stream));
43
 
44
  int memLevel = 8;          // Default.
45
  int windowBits = 15 + 16;  // Enable gzip header instead of zlib header.
46
 
47
  int retCode;
48
  if (deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY) != Z_OK) {
49
    return nil;
50
  }
51
 
52
  // Hint the size at 1/4 the input size.
53
  NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)];
54
  unsigned char output[kChunkSize];
55
 
56
  // Setup the input.
57
  strm.avail_in = (unsigned int)length;
58
  strm.next_in = (unsigned char *)bytes;
59
 
60
  // Collect the data.
61
  do {
62
    // update what we're passing in
63
    strm.avail_out = kChunkSize;
64
    strm.next_out = output;
65
    retCode = deflate(&strm, Z_FINISH);
66
    if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) {
67
      deflateEnd(&strm);
68
      return nil;
69
    }
70
    // Collect what we got.
71
    unsigned gotBack = kChunkSize - strm.avail_out;
72
    if (gotBack > 0) {
73
      [result appendBytes:output length:gotBack];
74
    }
75
 
76
  } while (retCode == Z_OK);
77
 
78
  // If the loop exits, it used all input and the stream ended.
79
  NSAssert(strm.avail_in == 0,
80
           @"Should have finished deflating without using all input, %u bytes left", strm.avail_in);
81
  NSAssert(retCode == Z_STREAM_END,
82
           @"thought we finished deflate w/o getting a result of stream end, code %d", retCode);
83
 
84
  // Clean up.
85
  deflateEnd(&strm);
86
 
87
  return result;
88
}
89
 
90
+ (BOOL)isGzipped:(NSData *)data {
91
  const UInt8 *bytes = (const UInt8 *)data.bytes;
92
  return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
93
}
94
 
95
@end