/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. #import <zlib.h>
  17. #import <stdlib.h>
  18. #import <assert.h>
  19. #import <stdio.h>
  20. #import <UIKit/UIKit.h>
  21. #import "ZipUtils.h"
  22. #import "ccMacros.h"
  23. int inflateMemory_(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength)
  24. {
  25. #if 1
  26. /* ret value */
  27. int err = Z_OK;
  28. /* 256k initial decompress buffer */
  29. int bufferSize = 256 * 1024;
  30. *out = (unsigned char*) malloc(bufferSize);
  31. z_stream d_stream; /* decompression stream */
  32. d_stream.zalloc = (alloc_func)0;
  33. d_stream.zfree = (free_func)0;
  34. d_stream.opaque = (voidpf)0;
  35. d_stream.next_in = in;
  36. d_stream.avail_in = inLength;
  37. d_stream.next_out = *out;
  38. d_stream.avail_out = bufferSize;
  39. /* window size to hold 256k */
  40. if( (err = inflateInit2(&d_stream, 15 + 32)) != Z_OK )
  41. return err;
  42. for (;;) {
  43. err = inflate(&d_stream, Z_NO_FLUSH);
  44. if (err == Z_STREAM_END)
  45. break;
  46. switch (err) {
  47. case Z_NEED_DICT:
  48. err = Z_DATA_ERROR;
  49. case Z_DATA_ERROR:
  50. case Z_MEM_ERROR:
  51. inflateEnd(&d_stream);
  52. return err;
  53. }
  54. // not enough memory ?
  55. if (err != Z_STREAM_END) {
  56. // memory in iPhone is precious
  57. // Should buffer factor be 1.5 instead of 2 ?
  58. #define BUFFER_INC_FACTOR (2)
  59. unsigned char *tmp = realloc(*out, bufferSize * BUFFER_INC_FACTOR);
  60. /* not enough memory, ouch */
  61. if (! tmp ) {
  62. CCLOG(@"cocos2d: ZipUtils: realloc failed");
  63. inflateEnd(&d_stream);
  64. return Z_MEM_ERROR;
  65. }
  66. /* only assign to *out if tmp is valid. it's not guaranteed that realloc will reuse the memory */
  67. *out = tmp;
  68. d_stream.next_out = *out + bufferSize;
  69. d_stream.avail_out = bufferSize;
  70. bufferSize *= BUFFER_INC_FACTOR;
  71. }
  72. }
  73. *outLength = bufferSize - d_stream.avail_out;
  74. err = inflateEnd(&d_stream);
  75. return err;
  76. #else
  77. return 0;
  78. #endif
  79. }
  80. int inflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
  81. {
  82. #if 1
  83. unsigned int outLength = 0;
  84. int err = inflateMemory_(in, inLength, out, &outLength);
  85. if (err != Z_OK || *out == NULL) {
  86. if (err == Z_MEM_ERROR)
  87. CCLOG(@"cocos2d: ZipUtils: Out of memory while decompressing map data!");
  88. else if (err == Z_VERSION_ERROR)
  89. CCLOG(@"cocos2d: ZipUtils: Incompatible zlib version!");
  90. else if (err == Z_DATA_ERROR)
  91. CCLOG(@"cocos2d: ZipUtils: Incorrect zlib compressed data!");
  92. else
  93. CCLOG(@"cocos2d: ZipUtils: Unknown error while decompressing map data!");
  94. free(*out);
  95. *out = NULL;
  96. outLength = 0;
  97. }
  98. return outLength;
  99. #else
  100. return 0;
  101. #endif
  102. }