PageRenderTime 38ms CodeModel.GetById 15ms app.highlight 20ms RepoModel.GetById 2ms app.codeStats 0ms

/libs/cocos2d/Support/ZipUtils.m

http://github.com/kstenerud/ObjectAL-for-iPhone
Objective C | 125 lines | 79 code | 23 blank | 23 comment | 21 complexity | 1c634509995e81257aaef3fc890cf1ed MD5 | raw file
  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}