include/ylt/standalone/cinatra/brzip.hpp (68 lines of code) (raw):

#pragma once #include <brotli/decode.h> #include <brotli/encode.h> #include <array> #include <sstream> #include <string> #include <string_view> namespace cinatra::br_codec { #define BROTLI_BUFFER_SIZE 1024 inline bool brotli_compress(std::string_view input, std::string &output) { auto instance = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr); std::array<uint8_t, BROTLI_BUFFER_SIZE> buffer; std::stringstream result; size_t available_in = input.size(), available_out = buffer.size(); const uint8_t *next_in = reinterpret_cast<const uint8_t *>(input.data()); uint8_t *next_out = buffer.data(); do { int ret = BrotliEncoderCompressStream(instance, BROTLI_OPERATION_FINISH, &available_in, &next_in, &available_out, &next_out, nullptr); if (!ret) return false; result.write(reinterpret_cast<const char *>(buffer.data()), buffer.size() - available_out); available_out = buffer.size(); next_out = buffer.data(); } while (!(available_in == 0 && BrotliEncoderIsFinished(instance))); BrotliEncoderDestroyInstance(instance); output = result.str(); return true; } inline bool brotli_decompress(std::string_view input, std::string &decompressed) { if (input.size() == 0) return false; size_t available_in = input.size(); auto next_in = (const uint8_t *)(input.data()); decompressed = std::string(available_in * 3, 0); size_t available_out = decompressed.size(); auto next_out = (uint8_t *)(decompressed.data()); size_t total_out{0}; bool done = false; auto s = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr); while (!done) { auto result = BrotliDecoderDecompressStream( s, &available_in, &next_in, &available_out, &next_out, &total_out); if (result == BROTLI_DECODER_RESULT_SUCCESS) { decompressed.resize(total_out); BrotliDecoderDestroyInstance(s); return true; } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { if (total_out != decompressed.size()) { return false; } decompressed.resize(total_out * 2); next_out = (uint8_t *)(decompressed.data() + total_out); available_out = total_out; } else { decompressed.resize(0); BrotliDecoderDestroyInstance(s); return true; } } return true; } } // namespace cinatra::br_codec // namespace cinatra::br_codec