| 279 | } |
| 280 | |
| 281 | std::string decompressFile(const std::filesystem::path& path) |
| 282 | { |
| 283 | std::string compressed = readFile(path); |
| 284 | |
| 285 | z_stream zs = {}; |
| 286 | // MAX_WBITS | 32 to support both zlib or gzip files. |
| 287 | if (inflateInit2(&zs, MAX_WBITS | 32) != Z_OK) |
| 288 | FALCOR_THROW("inflateInit2 failed while decompressing."); |
| 289 | |
| 290 | zs.next_in = reinterpret_cast<Bytef*>(compressed.data()); |
| 291 | zs.avail_in = (uInt)compressed.size(); |
| 292 | |
| 293 | int ret; |
| 294 | std::vector<char> buffer(128 * 1024); |
| 295 | std::string decompressed; |
| 296 | |
| 297 | // We can probably assume that the decompressed file is at least as large as the compressed one. |
| 298 | decompressed.reserve(compressed.size()); |
| 299 | |
| 300 | // Get the decompressed bytes blockwise using repeated calls to inflate. |
| 301 | do |
| 302 | { |
| 303 | zs.next_out = reinterpret_cast<Bytef*>(buffer.data()); |
| 304 | zs.avail_out = (uInt)buffer.size(); |
| 305 | |
| 306 | ret = inflate(&zs, 0); |
| 307 | |
| 308 | if (decompressed.size() < zs.total_out) |
| 309 | { |
| 310 | decompressed.append(buffer.data(), zs.total_out - decompressed.size()); |
| 311 | } |
| 312 | } while (ret == Z_OK); |
| 313 | |
| 314 | inflateEnd(&zs); |
| 315 | |
| 316 | // Check for errors. |
| 317 | if (ret != Z_STREAM_END) |
| 318 | { |
| 319 | FALCOR_THROW("Failure to decompress file '{}' (error: {}).", path, ret); |
| 320 | } |
| 321 | |
| 322 | return decompressed; |
| 323 | } |
| 324 | |
| 325 | std::string getStackTrace(size_t skip, size_t maxDepth) |
| 326 | { |