| 118 | |
| 119 | |
| 120 | extern int UncompressStringGZIP(const char * a_Data, size_t a_Length, AString & a_Uncompressed) |
| 121 | { |
| 122 | // Uncompresses a_Data into a_Uncompressed using GZIP; returns Z_OK for success or Z_XXX error constants same as zlib |
| 123 | |
| 124 | a_Uncompressed.reserve(a_Length); |
| 125 | |
| 126 | char Buffer[64 KiB]; |
| 127 | z_stream strm; |
| 128 | memset(&strm, 0, sizeof(strm)); |
| 129 | strm.next_in = (Bytef *)a_Data; |
| 130 | strm.avail_in = a_Length; |
| 131 | strm.next_out = (Bytef *)Buffer; |
| 132 | strm.avail_out = sizeof(Buffer); |
| 133 | |
| 134 | int res = inflateInit2(&strm, 31); // Force GZIP decoding |
| 135 | if (res != Z_OK) |
| 136 | { |
| 137 | LOG("%s: uncompression initialization failed: %d (\"%s\").", __FUNCTION__, res, strm.msg); |
| 138 | return res; |
| 139 | } |
| 140 | |
| 141 | for (;;) |
| 142 | { |
| 143 | res = inflate(&strm, Z_NO_FLUSH); |
| 144 | switch (res) |
| 145 | { |
| 146 | case Z_OK: |
| 147 | { |
| 148 | // Some data has been uncompressed. Consume the buffer and continue uncompressing |
| 149 | a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out); |
| 150 | strm.next_out = (Bytef *)Buffer; |
| 151 | strm.avail_out = sizeof(Buffer); |
| 152 | if (strm.avail_in == 0) |
| 153 | { |
| 154 | // All data has been uncompressed |
| 155 | inflateEnd(&strm); |
| 156 | return Z_OK; |
| 157 | } |
| 158 | break; |
| 159 | } |
| 160 | |
| 161 | case Z_STREAM_END: |
| 162 | { |
| 163 | // Finished uncompressing. Consume the rest of the buffer and return |
| 164 | a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out); |
| 165 | inflateEnd(&strm); |
| 166 | return Z_OK; |
| 167 | } |
| 168 | |
| 169 | default: |
| 170 | { |
| 171 | // An error has occurred, log it and return the error value |
| 172 | LOG("%s: uncompression failed: %d (\"%s\").", __FUNCTION__, res, strm.msg); |
| 173 | inflateEnd(&strm); |
| 174 | return res; |
| 175 | } |
| 176 | } // switch (res) |
| 177 | } // while (true) |
no test coverage detected