/libs/cocos2d/Support/ZipUtils.m
Objective C | 125 lines | 79 code | 23 blank | 23 comment | 21 complexity | 1c634509995e81257aaef3fc890cf1ed MD5 | raw file
Possible License(s): Apache-2.0
1/* cocos2d for iPhone 2 * 3 * http://www.cocos2d-iphone.org 4 * 5 * 6 * Inflates either zlib or gzip deflated memory. The inflated memory is 7 * expected to be freed by the caller. 8 * 9 * inflateMemory_ based on zlib example code 10 * http://www.zlib.net 11 * 12 * Some ideas were taken from: 13 * http://themanaworld.org/ 14 * from the mapreader.cpp file 15 */ 16 17#import <zlib.h> 18#import <stdlib.h> 19#import <assert.h> 20#import <stdio.h> 21#import <UIKit/UIKit.h> 22 23#import "ZipUtils.h" 24#import "ccMacros.h" 25 26int inflateMemory_(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength) 27{ 28#if 1 29 /* ret value */ 30 int err = Z_OK; 31 32 /* 256k initial decompress buffer */ 33 int bufferSize = 256 * 1024; 34 *out = (unsigned char*) malloc(bufferSize); 35 36 z_stream d_stream; /* decompression stream */ 37 d_stream.zalloc = (alloc_func)0; 38 d_stream.zfree = (free_func)0; 39 d_stream.opaque = (voidpf)0; 40 41 d_stream.next_in = in; 42 d_stream.avail_in = inLength; 43 d_stream.next_out = *out; 44 d_stream.avail_out = bufferSize; 45 46 /* window size to hold 256k */ 47 if( (err = inflateInit2(&d_stream, 15 + 32)) != Z_OK ) 48 return err; 49 50 for (;;) { 51 err = inflate(&d_stream, Z_NO_FLUSH); 52 53 if (err == Z_STREAM_END) 54 break; 55 56 switch (err) { 57 case Z_NEED_DICT: 58 err = Z_DATA_ERROR; 59 case Z_DATA_ERROR: 60 case Z_MEM_ERROR: 61 inflateEnd(&d_stream); 62 return err; 63 } 64 65 // not enough memory ? 66 if (err != Z_STREAM_END) { 67 68 // memory in iPhone is precious 69 // Should buffer factor be 1.5 instead of 2 ? 70#define BUFFER_INC_FACTOR (2) 71 unsigned char *tmp = realloc(*out, bufferSize * BUFFER_INC_FACTOR); 72 73 /* not enough memory, ouch */ 74 if (! tmp ) { 75 CCLOG(@"cocos2d: ZipUtils: realloc failed"); 76 inflateEnd(&d_stream); 77 return Z_MEM_ERROR; 78 } 79 /* only assign to *out if tmp is valid. it's not guaranteed that realloc will reuse the memory */ 80 *out = tmp; 81 82 d_stream.next_out = *out + bufferSize; 83 d_stream.avail_out = bufferSize; 84 bufferSize *= BUFFER_INC_FACTOR; 85 } 86 } 87 88 89 *outLength = bufferSize - d_stream.avail_out; 90 err = inflateEnd(&d_stream); 91 return err; 92#else 93 return 0; 94#endif 95} 96 97int inflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out) 98{ 99#if 1 100 unsigned int outLength = 0; 101 int err = inflateMemory_(in, inLength, out, &outLength); 102 103 if (err != Z_OK || *out == NULL) { 104 if (err == Z_MEM_ERROR) 105 CCLOG(@"cocos2d: ZipUtils: Out of memory while decompressing map data!"); 106 107 else if (err == Z_VERSION_ERROR) 108 CCLOG(@"cocos2d: ZipUtils: Incompatible zlib version!"); 109 110 else if (err == Z_DATA_ERROR) 111 CCLOG(@"cocos2d: ZipUtils: Incorrect zlib compressed data!"); 112 113 else 114 CCLOG(@"cocos2d: ZipUtils: Unknown error while decompressing map data!"); 115 116 free(*out); 117 *out = NULL; 118 outLength = 0; 119 } 120 121 return outLength; 122#else 123 return 0; 124#endif 125}