diff --git a/CMake/FindDeflate.cmake b/CMake/FindDeflate.cmake new file mode 100644 index 00000000..99aec8c8 --- /dev/null +++ b/CMake/FindDeflate.cmake @@ -0,0 +1,19 @@ +# Find package structure taken from libcurl + +include(FindPackageHandleStandardArgs) + +find_path(DEFLATE_INCLUDE_DIRS libdeflate.h) +find_library(DEFLATE_LIBRARY deflate) + +find_package_handle_standard_args(DEFLATE + FOUND_VAR + DEFLATE_FOUND + REQUIRED_VARS + DEFLATE_LIBRARY + DEFLATE_INCLUDE_DIRS + FAIL_MESSAGE + "Could NOT find deflate" +) + +set(DEFLATE_INCLUDE_DIRS ${DEFLATE_INCLUDE_DIRS}) +set(DEFLATE_LIBRARIES ${DEFLATE_LIBRARY}) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6564c77e..6b4dd893 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,14 @@ if (USE_ZLIB) target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_ZLIB) endif() +# brew install libdeflate +find_package(DEFLATE) +if (DEFLATE_FOUND) + include_directories(${DEFLATE_INCLUDE_DIRS}) + target_link_libraries(ixwebsocket ${DEFLATE_LIBRARIES}) + target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_DEFLATE) +endif() + if (WIN32) target_link_libraries(ixwebsocket wsock32 ws2_32 shlwapi) add_definitions(-D_CRT_SECURE_NO_WARNINGS) diff --git a/ixwebsocket/IXGzipCodec.cpp b/ixwebsocket/IXGzipCodec.cpp index b85fbada..d5e07c47 100644 --- a/ixwebsocket/IXGzipCodec.cpp +++ b/ixwebsocket/IXGzipCodec.cpp @@ -13,11 +13,55 @@ #include #endif +#ifdef IXWEBSOCKET_USE_DEFLATE +#include +#endif + namespace ix { #ifdef IXWEBSOCKET_USE_ZLIB std::string gzipCompress(const std::string& str) { +#ifdef IXWEBSOCKET_USE_DEFLATE + int compressionLevel = 6; + struct libdeflate_compressor *compressor = + libdeflate_alloc_compressor(compressionLevel); + + const void *uncompressed_data = str.data(); + size_t uncompressed_size = str.size(); + void *compressed_data; + size_t actual_compressed_size; + size_t max_compressed_size; + + max_compressed_size = libdeflate_gzip_compress_bound(compressor, + uncompressed_size); + compressed_data = malloc(max_compressed_size); + if (compressed_data == NULL) + { + return std::string(); + } + + actual_compressed_size = libdeflate_gzip_compress( + compressor, + uncompressed_data, + uncompressed_size, + compressed_data, + max_compressed_size); + + if (actual_compressed_size == 0) + { + free(compressed_data); + return std::string(); + } + + libdeflate_free_compressor(compressor); + + std::string out; + out.append(reinterpret_cast(compressed_data), actual_compressed_size); + free(compressed_data); + + return out; +#else z_stream zs; // z_stream is zlib's control structure memset(&zs, 0, sizeof(zs)); @@ -57,6 +101,7 @@ namespace ix deflateEnd(&zs); return outstring; +#endif } bool gzipDecompress(const std::string& in, std::string& out)