/
ZipUtils.m
125 lines (102 loc) · 2.8 KB
/
ZipUtils.m
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* cocos2d for iPhone
*
* http://www.cocos2d-iphone.org
*
*
* Inflates either zlib or gzip deflated memory. The inflated memory is
* expected to be freed by the caller.
*
* inflateMemory_ based on zlib example code
* http://www.zlib.net
*
* Some ideas were taken from:
* http://themanaworld.org/
* from the mapreader.cpp file
*/
#import <zlib.h>
#import <stdlib.h>
#import <assert.h>
#import <stdio.h>
#import <UIKit/UIKit.h>
#import "ZipUtils.h"
#import "ccMacros.h"
int inflateMemory_(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength)
{
#if 1
/* ret value */
int err = Z_OK;
/* 256k initial decompress buffer */
int bufferSize = 256 * 1024;
*out = (unsigned char*) malloc(bufferSize);
z_stream d_stream; /* decompression stream */
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = in;
d_stream.avail_in = inLength;
d_stream.next_out = *out;
d_stream.avail_out = bufferSize;
/* window size to hold 256k */
if( (err = inflateInit2(&d_stream, 15 + 32)) != Z_OK )
return err;
for (;;) {
err = inflate(&d_stream, Z_NO_FLUSH);
if (err == Z_STREAM_END)
break;
switch (err) {
case Z_NEED_DICT:
err = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&d_stream);
return err;
}
// not enough memory ?
if (err != Z_STREAM_END) {
// memory in iPhone is precious
// Should buffer factor be 1.5 instead of 2 ?
#define BUFFER_INC_FACTOR (2)
unsigned char *tmp = realloc(*out, bufferSize * BUFFER_INC_FACTOR);
/* not enough memory, ouch */
if (! tmp ) {
CCLOG(@"cocos2d: ZipUtils: realloc failed");
inflateEnd(&d_stream);
return Z_MEM_ERROR;
}
/* only assign to *out if tmp is valid. it's not guaranteed that realloc will reuse the memory */
*out = tmp;
d_stream.next_out = *out + bufferSize;
d_stream.avail_out = bufferSize;
bufferSize *= BUFFER_INC_FACTOR;
}
}
*outLength = bufferSize - d_stream.avail_out;
err = inflateEnd(&d_stream);
return err;
#else
return 0;
#endif
}
int inflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
{
#if 1
unsigned int outLength = 0;
int err = inflateMemory_(in, inLength, out, &outLength);
if (err != Z_OK || *out == NULL) {
if (err == Z_MEM_ERROR)
CCLOG(@"cocos2d: ZipUtils: Out of memory while decompressing map data!");
else if (err == Z_VERSION_ERROR)
CCLOG(@"cocos2d: ZipUtils: Incompatible zlib version!");
else if (err == Z_DATA_ERROR)
CCLOG(@"cocos2d: ZipUtils: Incorrect zlib compressed data!");
else
CCLOG(@"cocos2d: ZipUtils: Unknown error while decompressing map data!");
free(*out);
*out = NULL;
outLength = 0;
}
return outLength;
#else
return 0;
#endif
}