BinGZipFile.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include <cassert>
  2. #include <zlib.h>
  3. #include "Logger.h"
  4. #include "BinGZipFile.h"
  5. BinGZipFile::BinGZipFile(const Ogre::String& file):
  6. File(file),
  7. m_NumberOfFiles(0)
  8. {
  9. InnerGetNumberOfFiles();
  10. }
  11. BinGZipFile::BinGZipFile(File* pFile):
  12. File(pFile),
  13. m_NumberOfFiles(0)
  14. {
  15. InnerGetNumberOfFiles();
  16. }
  17. BinGZipFile::BinGZipFile(File* pFile, u32 offset, u32 length):
  18. File(pFile, offset, length),
  19. m_NumberOfFiles(0)
  20. {
  21. InnerGetNumberOfFiles();
  22. }
  23. BinGZipFile::BinGZipFile(u8* pBuffer, u32 offset, u32 length):
  24. File(pBuffer, offset, length),
  25. m_NumberOfFiles(0)
  26. {
  27. InnerGetNumberOfFiles();
  28. }
  29. BinGZipFile::~BinGZipFile()
  30. {
  31. }
  32. File*
  33. BinGZipFile::ExtractGZip(u32 fileNumber)
  34. {
  35. if (fileNumber >= m_NumberOfFiles)
  36. {
  37. return NULL;
  38. }
  39. u32 extract_size = 256 * 1024;
  40. u8* extract_buffer = (u8*)malloc(extract_size);
  41. int ret;
  42. z_stream strm;
  43. u32 offset = InnerGetFileOffset(fileNumber);
  44. strm.zalloc = Z_NULL; /* used to allocate the internal state */
  45. strm.zfree = Z_NULL; /* used to free the internal state */
  46. strm.opaque = Z_NULL; /* private data object passed to zalloc and zfree */
  47. strm.next_in = m_Buffer + offset; /* next input byte */
  48. strm.avail_in = m_BufferSize; /* number of bytes available at next_in */
  49. strm.next_out = extract_buffer; /* next output byte should be put there */
  50. strm.avail_out = extract_size; /* remaining free space at next_out */
  51. ret = inflateInit2(&strm, 15 + 32);
  52. if (ret != Z_OK)
  53. {
  54. switch (ret)
  55. {
  56. case Z_MEM_ERROR:
  57. inflateEnd(&strm);
  58. LOGGER->Log("Warning: inflateInit2 - Z_MEM_ERROR in file " + m_FileName);
  59. break;
  60. case Z_STREAM_ERROR:
  61. inflateEnd(&strm);
  62. LOGGER->Log("Warning: inflateInit2 - Z_STREAM_ERROR in file " + m_FileName);
  63. break;
  64. default:
  65. inflateEnd(&strm);
  66. LOGGER->Log("Warning: inflateInit2 - unknown error in file " + m_FileName);
  67. }
  68. return NULL;
  69. }
  70. do
  71. {
  72. if (strm.next_out == NULL)
  73. {
  74. inflateEnd(&strm);
  75. LOGGER->Log("Warning: strm.next_out == NULL in file " + m_FileName);
  76. return NULL;
  77. }
  78. ret = inflate(&strm, Z_NO_FLUSH);
  79. assert(ret != Z_STREAM_ERROR);
  80. switch (ret)
  81. {
  82. case Z_NEED_DICT:
  83. inflateEnd(&strm);
  84. LOGGER->Log("Warning: inflate - Z_NEED_DICT in file " + m_FileName);
  85. return NULL;
  86. case Z_DATA_ERROR:
  87. inflateEnd(&strm);
  88. LOGGER->Log("Warning: inflate - Z_DATA_ERROR in file " + m_FileName);
  89. return NULL;
  90. case Z_MEM_ERROR:
  91. inflateEnd(&strm);
  92. LOGGER->Log("Warning: inflate - Z_MEM_ERROR in file " + m_FileName);
  93. return NULL;
  94. }
  95. if (ret != Z_STREAM_END)
  96. {
  97. extract_buffer = (u8*)realloc(extract_buffer, extract_size * 2);
  98. if (extract_buffer == NULL)
  99. {
  100. inflateEnd(&strm);
  101. LOGGER->Log("Warning: extract_buffer == NULL in file " + m_FileName);
  102. return NULL;
  103. }
  104. strm.next_out = (u8*)extract_buffer + extract_size;
  105. strm.avail_out = extract_size;
  106. extract_size *= 2;
  107. }
  108. }
  109. while (ret != Z_STREAM_END);
  110. extract_size = extract_size - strm.avail_out;
  111. (void)inflateEnd(&strm);
  112. if (ret != Z_STREAM_END)
  113. {
  114. LOGGER->Log("Warning: ret != Z_STREAM_END in file " + m_FileName);
  115. return NULL;
  116. }
  117. File* file = new File(extract_buffer, 0, extract_size);
  118. free(extract_buffer);
  119. return file;
  120. }
  121. u32
  122. BinGZipFile::GetNumberOfFiles()
  123. {
  124. return m_NumberOfFiles;
  125. }
  126. void
  127. BinGZipFile::InnerGetNumberOfFiles()
  128. {
  129. m_NumberOfFiles = 0;
  130. for (u32 pointer = 0; pointer < m_BufferSize;)
  131. {
  132. u16 temp = GetU16LE(pointer);
  133. pointer += 6;
  134. // condition for gzip header
  135. if (GetU32LE(pointer) == 0x00088B1F && GetU32LE(pointer + 4) == 0x00000000)
  136. {
  137. ++m_NumberOfFiles;
  138. }
  139. pointer += temp;
  140. }
  141. if (m_NumberOfFiles == 0)
  142. {
  143. LOGGER->Log("Warning: " + m_FileName + " isn't archive. number_of_files == 0");
  144. }
  145. }
  146. u32
  147. BinGZipFile::InnerGetFileOffset(u32 fileNumber)
  148. {
  149. if (fileNumber >= m_NumberOfFiles)
  150. {
  151. return 0;
  152. }
  153. u32 current_file = 0;
  154. for (u32 pointer = 0; pointer < m_BufferSize;)
  155. {
  156. u16 temp = GetU16LE(pointer);
  157. pointer += 6;
  158. // condition for gzip header
  159. if (GetU32LE(pointer) == 0x00088B1F && GetU32LE(pointer + 4) == 0x00000000)
  160. {
  161. if (fileNumber == current_file)
  162. {
  163. return pointer;
  164. }
  165. }
  166. ++current_file;
  167. pointer += temp;
  168. }
  169. return 0;
  170. }