diff --git a/source/framework/tools/inc/TRestTools.h b/source/framework/tools/inc/TRestTools.h index 6b7a16c89..ec72278e9 100644 --- a/source/framework/tools/inc/TRestTools.h +++ b/source/framework/tools/inc/TRestTools.h @@ -129,6 +129,8 @@ class TRestTools { static std::string POSTRequest(const std::string& url, const std::map& keys); static void ChangeDirectory(const std::string& toDirectory); + + static bool GzipInflate(const std::string& compressedBytes, std::string& uncompressedBytes); }; namespace REST_InitTools { diff --git a/source/framework/tools/src/TRestTools.cxx b/source/framework/tools/src/TRestTools.cxx index ab2b2c7b7..c2719063c 100644 --- a/source/framework/tools/src/TRestTools.cxx +++ b/source/framework/tools/src/TRestTools.cxx @@ -51,6 +51,9 @@ #include #endif +#include "zconf.h" +#include "zlib.h" + #ifdef WIN32 #include #else @@ -1264,3 +1267,69 @@ string ToTimeStringLong(double seconds) { return TString::Format("%.2f %s", seconds / (60.0 * 60.0 * 24.0), "days").Data(); } } + +/////////////////////////////////////////////// +/// It will decompress a std::string that has been initialized from a gzip file. +/// +bool TRestTools::GzipInflate(const std::string& compressedBytes, std::string& uncompressedBytes) { + if (compressedBytes.size() == 0) { + uncompressedBytes = compressedBytes; + return true; + } + + uncompressedBytes.clear(); + + unsigned full_length = compressedBytes.size(); + unsigned half_length = compressedBytes.size() / 2; + + unsigned uncompLength = full_length; + char* uncomp = (char*)calloc(sizeof(char), uncompLength); + + z_stream strm; + strm.next_in = (Bytef*)compressedBytes.c_str(); + strm.avail_in = compressedBytes.size(); + strm.total_out = 0; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + + bool done = false; + + if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) { + free(uncomp); + return false; + } + + while (!done) { + // If our output buffer is too small + if (strm.total_out >= uncompLength) { + // Increase size of output buffer + char* uncomp2 = (char*)calloc(sizeof(char), uncompLength + half_length); + memcpy(uncomp2, uncomp, uncompLength); + uncompLength += half_length; + free(uncomp); + uncomp = uncomp2; + } + + strm.next_out = (Bytef*)(uncomp + strm.total_out); + strm.avail_out = uncompLength - strm.total_out; + + // Inflate another chunk. + int err = inflate(&strm, Z_SYNC_FLUSH); + if (err == Z_STREAM_END) + done = true; + else if (err != Z_OK) { + break; + } + } + + if (inflateEnd(&strm) != Z_OK) { + free(uncomp); + return false; + } + + for (size_t i = 0; i < strm.total_out; ++i) { + uncompressedBytes += uncomp[i]; + } + free(uncomp); + return true; +}