#include "gzip_utils.hpp" #include #include #include #include #include #include #include #include std::optional gzipInflate(std::span compressedBytes) { std::string uncompressedBytes; if (compressedBytes.empty()) { return std::nullopt; } z_stream strm{ }; strm.next_in = (Bytef*)compressedBytes.data(); strm.avail_in = static_cast(compressedBytes.size()); strm.total_out = 0; if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) { return std::nullopt; } while (strm.avail_in > 0) { constexpr size_t chunkSize = 1024; uncompressedBytes.resize(uncompressedBytes.size() + chunkSize); strm.next_out = std::bit_cast(uncompressedBytes.end() - chunkSize); strm.avail_out = chunkSize; // Inflate another chunk. int err = inflate(&strm, Z_SYNC_FLUSH); if (err == Z_STREAM_END) { break; } if (err != Z_OK) { return std::nullopt; } } if (inflateEnd(&strm) != Z_OK) { return std::nullopt; } uncompressedBytes.resize(strm.total_out); return {uncompressedBytes}; } static std::vector xpathText(xmlDocPtr doc, const char* xp) { std::vector val; xmlXPathContextPtr ctx = xmlXPathNewContext(doc); if (ctx == nullptr) { return val; } const unsigned char* xpptr = std::bit_cast(xp); xmlXPathObjectPtr obj = xmlXPathEvalExpression(xpptr, ctx); if (obj != nullptr) { if (obj->type == XPATH_NODESET && obj->nodesetval != nullptr) { xmlNodeSetPtr nodeTab = obj->nodesetval; size_t nodeNr = static_cast(nodeTab->nodeNr); std::span nodes{nodeTab->nodeTab, nodeNr}; for (xmlNodePtr node : nodes) { unsigned char* keyword = xmlNodeGetContent(node); val.emplace_back(std::bit_cast(keyword)); xmlFree(keyword); } } } xmlXPathFreeObject(obj); xmlXPathFreeContext(ctx); return val; } std::vector getNodeFromXml(std::string_view xml, const char* nodeName) { std::vector node; if (xml.empty()) { return node; } xmlDocPtr doc = xmlReadMemory( xml.data(), xml.size(), nullptr, nullptr, XML_PARSE_RECOVER | XML_PARSE_NONET | XML_PARSE_NOWARNING); if (doc == nullptr) { return {}; } node = xpathText(doc, nodeName); xmlFreeDoc(doc); return node; }