SeekableZStream.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  3. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #ifndef SeekableZStream_h
  5. #define SeekableZStream_h
  6. #include "Zip.h"
  7. /**
  8. * Seekable compressed stream are created by splitting the original
  9. * decompressed data in small chunks and compress these chunks
  10. * individually.
  11. *
  12. * The seekable compressed file format consists in a header defined below,
  13. * followed by a table of 32-bits words containing the offsets for each
  14. * individual compressed chunk, then followed by the compressed chunks.
  15. */
  16. #pragma pack(1)
  17. struct SeekableZStreamHeader: public Zip::SignedEntity<SeekableZStreamHeader>
  18. {
  19. SeekableZStreamHeader()
  20. : Zip::SignedEntity<SeekableZStreamHeader>(magic)
  21. , totalSize(0), chunkSize(0), dictSize(0), nChunks(0), lastChunkSize(0)
  22. , windowBits(0), filter(0) { }
  23. /* Reuse Zip::SignedEntity to handle the magic number used in the Seekable
  24. * ZStream file format. The magic number is "SeZz". */
  25. static const uint32_t magic = 0x7a5a6553;
  26. /* Total size of the stream, including the 4 magic bytes. */
  27. le_uint32 totalSize;
  28. /* Chunk size */
  29. le_uint16 chunkSize;
  30. /* Size of the dictionary */
  31. le_uint16 dictSize;
  32. /* Number of chunks */
  33. le_uint32 nChunks;
  34. /* Size of last chunk (> 0, <= Chunk size) */
  35. le_uint16 lastChunkSize;
  36. /* windowBits value used when deflating */
  37. signed char windowBits;
  38. /* Filter Id */
  39. unsigned char filter;
  40. };
  41. #pragma pack()
  42. static_assert(sizeof(SeekableZStreamHeader) == 5 * 4,
  43. "SeekableZStreamHeader should be 5 32-bits words");
  44. /**
  45. * Helper class used to decompress Seekable ZStreams.
  46. */
  47. class SeekableZStream {
  48. public:
  49. /* Initialize from the given buffer. Returns whether initialization
  50. * succeeded (true) or failed (false). */
  51. bool Init(const void *buf, size_t length);
  52. /* Decompresses starting from the given chunk. The decompressed data is
  53. * stored at the given location. The given length, in bytes, indicates
  54. * how much data to decompress. If length is 0, then exactly one chunk
  55. * is decompressed.
  56. * Returns whether decompression succeeded (true) or failed (false). */
  57. bool Decompress(void *where, size_t chunk, size_t length = 0);
  58. /* Decompresses the given chunk at the given address. If a length is given,
  59. * only decompresses that amount of data instead of the entire chunk.
  60. * Returns whether decompression succeeded (true) or failed (false). */
  61. bool DecompressChunk(void *where, size_t chunk, size_t length = 0);
  62. /* Returns the uncompressed size of the complete zstream */
  63. size_t GetUncompressedSize() const
  64. {
  65. return (offsetTable.numElements() - 1) * chunkSize + lastChunkSize;
  66. }
  67. /* Returns the chunk size of the given chunk */
  68. size_t GetChunkSize(size_t chunk = 0) const {
  69. return (chunk == offsetTable.numElements() - 1) ? lastChunkSize : chunkSize;
  70. }
  71. /* Returns the number of chunks */
  72. size_t GetChunksNum() const {
  73. return offsetTable.numElements();
  74. }
  75. /**
  76. * Filters used to improve compression rate.
  77. */
  78. enum FilterDirection {
  79. FILTER,
  80. UNFILTER
  81. };
  82. typedef void (*ZStreamFilter)(off_t, FilterDirection,
  83. unsigned char *, size_t);
  84. enum FilterId {
  85. NONE,
  86. BCJ_THUMB,
  87. BCJ_ARM,
  88. BCJ_X86,
  89. FILTER_MAX
  90. };
  91. static ZStreamFilter GetFilter(FilterId id);
  92. static ZStreamFilter GetFilter(uint16_t id) {
  93. return GetFilter(static_cast<FilterId>(id));
  94. }
  95. private:
  96. /* RAW Seekable SZtream buffer */
  97. const unsigned char *buffer;
  98. /* Total size of the stream, including the 4 magic bytes. */
  99. uint32_t totalSize;
  100. /* Chunk size */
  101. uint32_t chunkSize;
  102. /* Size of last chunk (> 0, <= Chunk size) */
  103. uint32_t lastChunkSize;
  104. /* windowBits value used when deflating */
  105. int windowBits;
  106. /* Offsets table */
  107. Array<le_uint32> offsetTable;
  108. /* Filter */
  109. ZStreamFilter filter;
  110. /* Deflate dictionary */
  111. Array<unsigned char> dictionary;
  112. /* Special allocator for inflate to use the same buffers for every chunk */
  113. zxx_stream::StaticAllocator allocator;
  114. };
  115. inline void
  116. operator++(SeekableZStream::FilterId &other)
  117. {
  118. const int orig = static_cast<int>(other);
  119. other = static_cast<SeekableZStream::FilterId>(orig + 1);
  120. }
  121. #endif /* SeekableZStream_h */