CCompressedStream.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * CCompressedStream.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include "CInputStream.h"
  12. struct z_stream_s;
  13. VCMI_LIB_NAMESPACE_BEGIN
  14. class DecompressionException : public std::runtime_error
  15. {
  16. public:
  17. using runtime_error::runtime_error;
  18. };
  19. /// Abstract class that provides buffer for one-directional input streams (e.g. compressed data)
  20. /// Used for zip archives support and in .lod deflate compression
  21. class CBufferedStream : public CInputStream
  22. {
  23. public:
  24. CBufferedStream();
  25. /**
  26. * Reads n bytes from the stream into the data buffer.
  27. *
  28. * @param data A pointer to the destination data array.
  29. * @param size The number of bytes to read.
  30. * @return the number of bytes read actually.
  31. *
  32. * @throws std::runtime_error if the file decompression was not successful
  33. */
  34. si64 read(ui8 * data, si64 size) override;
  35. /**
  36. * Seeks the internal read pointer to the specified position.
  37. * This will cause decompressing data till this position is found
  38. *
  39. * @param position The read position from the beginning.
  40. * @return the position actually moved to, -1 on error.
  41. */
  42. si64 seek(si64 position) override;
  43. /**
  44. * Gets the current read position in the stream.
  45. *
  46. * @return the read position.
  47. */
  48. si64 tell() override;
  49. /**
  50. * Skips delta numbers of bytes.
  51. *
  52. * @param delta The count of bytes to skip.
  53. * @return the count of bytes skipped actually.
  54. */
  55. si64 skip(si64 delta) override;
  56. /**
  57. * Gets the length in bytes of the stream.
  58. * Causes complete data decompression
  59. *
  60. * @return the length in bytes of the stream.
  61. */
  62. si64 getSize() override;
  63. protected:
  64. /**
  65. * @brief virtual method to get more data into the buffer
  66. * @return amount of bytes actually read, non-positive values are considered to be end-of-file mark
  67. */
  68. virtual si64 readMore(ui8 * data, si64 size) = 0;
  69. /// resets all internal state
  70. void reset();
  71. private:
  72. /// ensures that buffer contains at lest size of bytes. Calls readMore() to fill remaining part
  73. void ensureSize(si64 size);
  74. /** buffer with already decompressed data */
  75. std::vector<ui8> buffer;
  76. /** Current read position */
  77. si64 position;
  78. bool endOfFileReached;
  79. };
  80. /**
  81. * A class which provides method definitions for reading a gzip-compressed file
  82. * This class implements lazy loading - data will be decompressed (and cached) only by request
  83. */
  84. class DLL_LINKAGE CCompressedStream : public CBufferedStream
  85. {
  86. public:
  87. /**
  88. * C-tor.
  89. *
  90. * @param stream - stream with compressed data
  91. * @param gzip - this is gzipp'ed file e.g. campaign or maps, false for files in .lod
  92. * @param decompressedSize - optional parameter to hint size of decompressed data
  93. */
  94. CCompressedStream(std::unique_ptr<CInputStream> stream, bool gzip, size_t decompressedSize=0);
  95. ~CCompressedStream();
  96. /**
  97. * Prepare stream for decompression of next block (e.g. next part of h3c)
  98. * Applicable only for streams that contain multiple concatenated compressed data
  99. *
  100. * @return false if next block was not found, true othervice
  101. */
  102. bool getNextBlock();
  103. private:
  104. /**
  105. * Decompresses data to ensure that buffer has newSize bytes or end of stream was reached
  106. */
  107. si64 readMore(ui8 * data, si64 size) override;
  108. /** The file stream with compressed data. */
  109. std::unique_ptr<CInputStream> gzipStream;
  110. /** buffer with not yet decompressed data*/
  111. std::vector<ui8> compressedBuffer;
  112. /** struct with current zlib inflate state */
  113. std::unique_ptr<z_stream_s> inflateState;
  114. enum EState
  115. {
  116. ERROR_OCCURRED,
  117. INITIALIZED,
  118. IN_PROGRESS,
  119. STREAM_END,
  120. FINISHED
  121. };
  122. };
  123. VCMI_LIB_NAMESPACE_END