1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mozglue/linker/SeekableZStream.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,151 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef SeekableZStream_h 1.9 +#define SeekableZStream_h 1.10 + 1.11 +#include "Zip.h" 1.12 + 1.13 +/** 1.14 + * Seekable compressed stream are created by splitting the original 1.15 + * decompressed data in small chunks and compress these chunks 1.16 + * individually. 1.17 + * 1.18 + * The seekable compressed file format consists in a header defined below, 1.19 + * followed by a table of 32-bits words containing the offsets for each 1.20 + * individual compressed chunk, then followed by the compressed chunks. 1.21 + */ 1.22 + 1.23 +#pragma pack(1) 1.24 +struct SeekableZStreamHeader: public Zip::SignedEntity<SeekableZStreamHeader> 1.25 +{ 1.26 + SeekableZStreamHeader() 1.27 + : Zip::SignedEntity<SeekableZStreamHeader>(magic) 1.28 + , totalSize(0), chunkSize(0), dictSize(0), nChunks(0), lastChunkSize(0) 1.29 + , windowBits(0), filter(0) { } 1.30 + 1.31 + /* Reuse Zip::SignedEntity to handle the magic number used in the Seekable 1.32 + * ZStream file format. The magic number is "SeZz". */ 1.33 + static const uint32_t magic = 0x7a5a6553; 1.34 + 1.35 + /* Total size of the stream, including the 4 magic bytes. */ 1.36 + le_uint32 totalSize; 1.37 + 1.38 + /* Chunk size */ 1.39 + le_uint16 chunkSize; 1.40 + 1.41 + /* Size of the dictionary */ 1.42 + le_uint16 dictSize; 1.43 + 1.44 + /* Number of chunks */ 1.45 + le_uint32 nChunks; 1.46 + 1.47 + /* Size of last chunk (> 0, <= Chunk size) */ 1.48 + le_uint16 lastChunkSize; 1.49 + 1.50 + /* windowBits value used when deflating */ 1.51 + signed char windowBits; 1.52 + 1.53 + /* Filter Id */ 1.54 + unsigned char filter; 1.55 +}; 1.56 +#pragma pack() 1.57 + 1.58 +static_assert(sizeof(SeekableZStreamHeader) == 5 * 4, 1.59 + "SeekableZStreamHeader should be 5 32-bits words"); 1.60 + 1.61 +/** 1.62 + * Helper class used to decompress Seekable ZStreams. 1.63 + */ 1.64 +class SeekableZStream { 1.65 +public: 1.66 + /* Initialize from the given buffer. Returns whether initialization 1.67 + * succeeded (true) or failed (false). */ 1.68 + bool Init(const void *buf, size_t length); 1.69 + 1.70 + /* Decompresses starting from the given chunk. The decompressed data is 1.71 + * stored at the given location. The given length, in bytes, indicates 1.72 + * how much data to decompress. If length is 0, then exactly one chunk 1.73 + * is decompressed. 1.74 + * Returns whether decompression succeeded (true) or failed (false). */ 1.75 + bool Decompress(void *where, size_t chunk, size_t length = 0); 1.76 + 1.77 + /* Decompresses the given chunk at the given address. If a length is given, 1.78 + * only decompresses that amount of data instead of the entire chunk. 1.79 + * Returns whether decompression succeeded (true) or failed (false). */ 1.80 + bool DecompressChunk(void *where, size_t chunk, size_t length = 0); 1.81 + 1.82 + /* Returns the uncompressed size of the complete zstream */ 1.83 + const size_t GetUncompressedSize() const 1.84 + { 1.85 + return (offsetTable.numElements() - 1) * chunkSize + lastChunkSize; 1.86 + } 1.87 + 1.88 + /* Returns the chunk size of the given chunk */ 1.89 + const size_t GetChunkSize(size_t chunk = 0) const { 1.90 + return (chunk == offsetTable.numElements() - 1) ? lastChunkSize : chunkSize; 1.91 + } 1.92 + 1.93 + /* Returns the number of chunks */ 1.94 + const size_t GetChunksNum() const { 1.95 + return offsetTable.numElements(); 1.96 + } 1.97 + 1.98 + /** 1.99 + * Filters used to improve compression rate. 1.100 + */ 1.101 + enum FilterDirection { 1.102 + FILTER, 1.103 + UNFILTER 1.104 + }; 1.105 + typedef void (*ZStreamFilter)(off_t, FilterDirection, 1.106 + unsigned char *, size_t); 1.107 + 1.108 + enum FilterId { 1.109 + NONE, 1.110 + BCJ_THUMB, 1.111 + BCJ_ARM, 1.112 + BCJ_X86, 1.113 + FILTER_MAX 1.114 + }; 1.115 + static ZStreamFilter GetFilter(FilterId id); 1.116 + 1.117 + static ZStreamFilter GetFilter(uint16_t id) { 1.118 + return GetFilter(static_cast<FilterId>(id)); 1.119 + } 1.120 + 1.121 +private: 1.122 + /* RAW Seekable SZtream buffer */ 1.123 + const unsigned char *buffer; 1.124 + 1.125 + /* Total size of the stream, including the 4 magic bytes. */ 1.126 + uint32_t totalSize; 1.127 + 1.128 + /* Chunk size */ 1.129 + uint32_t chunkSize; 1.130 + 1.131 + /* Size of last chunk (> 0, <= Chunk size) */ 1.132 + uint32_t lastChunkSize; 1.133 + 1.134 + /* windowBits value used when deflating */ 1.135 + int windowBits; 1.136 + 1.137 + /* Offsets table */ 1.138 + Array<le_uint32> offsetTable; 1.139 + 1.140 + /* Filter */ 1.141 + ZStreamFilter filter; 1.142 + 1.143 + /* Deflate dictionary */ 1.144 + Array<unsigned char> dictionary; 1.145 +}; 1.146 + 1.147 +inline void 1.148 +operator++(SeekableZStream::FilterId &other) 1.149 +{ 1.150 + const int orig = static_cast<int>(other); 1.151 + other = static_cast<SeekableZStream::FilterId>(orig + 1); 1.152 +} 1.153 + 1.154 +#endif /* SeekableZStream_h */