CommonMPQ.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /* zpipe.c: example of proper use of zlib's inflate() and deflate()
  2. Not copyrighted -- provided to the public domain
  3. Version 1.4 11 December 2005 Mark Adler */
  4. /* Version history:
  5. 1.0 30 Oct 2004 First version
  6. 1.1 8 Nov 2004 Add void casting for unused return values
  7. Use switch statement for inflate() return values
  8. 1.2 9 Nov 2004 Add assertions to document zlib guarantees
  9. 1.3 6 Apr 2005 Remove incorrect assertion in inf()
  10. 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions
  11. Avoid some compiler warnings for input and output buffers
  12. */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <assert.h>
  16. #include "zlib.h"
  17. #include "CommonMPQ.h"
  18. #define CHUNK 16384
  19. int unzip_progress = 0;
  20. int inf(FILE *source, FILE *dest)
  21. {
  22. unzip_progress = 0;
  23. int ret;
  24. unsigned have;
  25. z_stream strm;
  26. unsigned char in[CHUNK];
  27. unsigned char out[CHUNK];
  28. /* allocate inflate state */
  29. strm.zalloc = Z_NULL;
  30. strm.zfree = Z_NULL;
  31. strm.opaque = Z_NULL;
  32. strm.avail_in = 0;
  33. strm.next_in = Z_NULL;
  34. ret = inflateInit(&strm);
  35. if (ret != Z_OK)
  36. return ret;
  37. /* decompress until deflate stream ends or end of file */
  38. do {
  39. strm.avail_in = fread(in, 1, CHUNK, source);
  40. if (ferror(source)) {
  41. (void)inflateEnd(&strm);
  42. return Z_ERRNO;
  43. }
  44. if (strm.avail_in == 0)
  45. break;
  46. strm.next_in = in;
  47. /* run inflate() on input until output buffer not full */
  48. do {
  49. strm.avail_out = CHUNK;
  50. strm.next_out = out;
  51. ret = inflate(&strm, Z_NO_FLUSH);
  52. assert(ret != Z_STREAM_ERROR); /* state not clobbered */
  53. switch (ret) {
  54. case Z_NEED_DICT:
  55. ret = Z_DATA_ERROR; /* and fall through */
  56. case Z_DATA_ERROR:
  57. case Z_MEM_ERROR:
  58. (void)inflateEnd(&strm);
  59. return ret;
  60. }
  61. have = CHUNK - strm.avail_out;
  62. if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
  63. (void)inflateEnd(&strm);
  64. return Z_ERRNO;
  65. }
  66. unzip_progress += have;
  67. } while (strm.avail_out == 0);
  68. /* done when inflate() says it's done */
  69. } while (ret != Z_STREAM_END);
  70. /* clean up and return */
  71. (void)inflateEnd(&strm);
  72. return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
  73. }
  74. int buff_read(unsigned char* dst, unsigned char* src, int s_offset, int s_end, int count)
  75. {
  76. int c = s_end - s_offset;
  77. if (c == 0) { return 0; }
  78. if (c < count){ count = c; }
  79. memcpy(dst, src + s_offset, count);
  80. return c;
  81. }
  82. int buff_write(unsigned char* dst, int d_offset, int d_end, unsigned char* src, int count)
  83. {
  84. int c = d_end - d_offset;
  85. if (c == 0) { return 0; }
  86. if (c < count){ count = c; }
  87. memcpy(dst + d_offset, src, count);
  88. return c;
  89. }
  90. int inf_mem(unsigned char* src, int s_start, int s_end, unsigned char* dst, int dst_start, int dst_end)
  91. {
  92. int ret;
  93. unsigned have;
  94. z_stream strm;
  95. unsigned char in[CHUNK];
  96. unsigned char out[CHUNK];
  97. /* allocate inflate state */
  98. strm.zalloc = Z_NULL;
  99. strm.zfree = Z_NULL;
  100. strm.opaque = Z_NULL;
  101. strm.avail_in = 0;
  102. strm.next_in = Z_NULL;
  103. ret = inflateInit(&strm);
  104. if (ret != Z_OK)
  105. return ret;
  106. /* decompress until deflate stream ends or end of file */
  107. do {
  108. strm.avail_in = buff_read(in, src, s_start, s_end, CHUNK);
  109. s_start += strm.avail_in;
  110. if (strm.avail_in == 0)
  111. break;
  112. strm.next_in = in;
  113. /* run inflate() on input until output buffer not full */
  114. do {
  115. strm.avail_out = CHUNK;
  116. strm.next_out = out;
  117. ret = inflate(&strm, Z_NO_FLUSH);
  118. assert(ret != Z_STREAM_ERROR); /* state not clobbered */
  119. switch (ret) {
  120. case Z_NEED_DICT:
  121. ret = Z_DATA_ERROR; /* and fall through */
  122. case Z_DATA_ERROR:
  123. case Z_MEM_ERROR:
  124. (void)inflateEnd(&strm);
  125. return ret;
  126. }
  127. have = CHUNK - strm.avail_out;
  128. dst_start += buff_write(dst, dst_start, dst_end, out, have);
  129. } while (strm.avail_out == 0);
  130. /* done when inflate() says it's done */
  131. } while (ret != Z_STREAM_END);
  132. /* clean up and return */
  133. (void)inflateEnd(&strm);
  134. return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
  135. }
  136. bool _Decompress_z(const char * src_file, const char * dst_file)
  137. {
  138. FILE *srcF = fopen(src_file, "rb");
  139. FILE *dstF = fopen(dst_file, "wb");
  140. if (NULL == srcF || NULL == dstF)
  141. {
  142. if (srcF) fclose(srcF);
  143. if (dstF) fclose(dstF);
  144. return false;
  145. }
  146. bool ret = (inf(srcF, dstF) == Z_OK);
  147. if (srcF) fclose(srcF);
  148. if (dstF) fclose(dstF);
  149. return ret;
  150. }
  151. bool _Decompress_z_mem(unsigned char* src, int s_start, int s_end, unsigned char* dst, int dst_start, int dst_end)
  152. {
  153. return inf_mem(src, s_start, s_end, dst, dst_start, dst_end) == Z_OK;
  154. }
  155. int _Decompress_bytes()
  156. {
  157. return unzip_progress;
  158. }