Skip to content

Commit

Permalink
feat: Added basic support for lz4 decompression to the pattern language
Browse files Browse the repository at this point in the history
  • Loading branch information
WerWolv committed Jul 7, 2024
1 parent 0cbc65a commit 1f5e4ce
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 16 deletions.
60 changes: 60 additions & 0 deletions cmake/modules/FindLZ4.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
find_path(LZ4_INCLUDE_DIR
NAMES lz4.h
HINTS "${LZ4_INCLUDEDIR}" "${LZ4_HINTS}/include"
PATHS
/usr/local/include
/usr/include
)

find_library(LZ4_LIBRARY
NAMES lz4 liblz4
HINTS "${LZ4_LIBDIR}" "${LZ4_HINTS}/lib"
PATHS
/usr/local/lib
/usr/lib
)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args( LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR )

if( LZ4_FOUND )
include( CheckIncludeFile )
include( CMakePushCheckState )

set( LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR} )
set( LZ4_LIBRARIES ${LZ4_LIBRARY} )

cmake_push_check_state()
set( CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIRS} )
check_include_file( lz4frame.h HAVE_LZ4FRAME_H )
cmake_pop_check_state()

if (WIN32)
set ( LZ4_DLL_DIR "${LZ4_HINTS}/bin"
CACHE PATH "Path to LZ4 DLL"
)
file( GLOB _lz4_dll RELATIVE "${LZ4_DLL_DIR}"
"${LZ4_DLL_DIR}/lz4*.dll"
)
set ( LZ4_DLL ${_lz4_dll}
# We're storing filenames only. Should we use STRING instead?
CACHE FILEPATH "LZ4 DLL file name"
)
file( GLOB _lz4_pdb RELATIVE "${LZ4_DLL_DIR}"
"${LZ4_DLL_DIR}/lz4*.pdb"
)
set ( LZ4_PDB ${_lz4_pdb}
CACHE FILEPATH "LZ4 PDB file name"
)
mark_as_advanced( LZ4_DLL_DIR LZ4_DLL LZ4_PDB )
endif()
else()
set( LZ4_INCLUDE_DIRS )
set( LZ4_LIBRARIES )
endif()

mark_as_advanced( LZ4_LIBRARIES LZ4_INCLUDE_DIRS )

add_library( LZ4::lz4 INTERFACE IMPORTED )
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${LZ4_INCLUDE_DIRS} )
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_LINK_LIBRARIES ${LZ4_LIBRARIES} )
6 changes: 5 additions & 1 deletion cmake/modules/FindZSTD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@ if (ZSTD_FOUND)
message(STATUS "Found Zstd: ${ZSTD_LIBRARY}")
endif()

mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)

add_library(ZSTD::zstd INTERFACE IMPORTED)
set_property(TARGET ZSTD::zstd PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${ZSTD_INCLUDE_DIR})
set_property(TARGET ZSTD::zstd PROPERTY INTERFACE_LINK_LIBRARIES ${ZSTD_LIBRARY})
1 change: 1 addition & 0 deletions dist/ImHex-9999.ebuild
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ RDEPEND="${DEPEND}
app-arch/bzip2
app-arch/lzma
app-arch/zstd
app-arch/lz4
"
BDEPEND="${DEPEND}"
3 changes: 2 additions & 1 deletion dist/get_deps_archlinux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ pacman -S $@ --needed \
zlib \
bzip2 \
xz \
zstd
zstd \
lz4
3 changes: 2 additions & 1 deletion dist/get_deps_debian.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ apt install -y \
zlib1g-dev \
libbz2-dev \
liblzma-dev \
libzstd-dev
libzstd-dev \
liblz4-dev
3 changes: 2 additions & 1 deletion dist/get_deps_fedora.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ dnf install -y \
libzstd-devel \
zlib-devel \
bzip2-devel \
xz-devel
xz-devel \
lz4-devel
3 changes: 2 additions & 1 deletion dist/get_deps_msys2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ pacboy -S --needed --noconfirm \
zlib:p \
bzip2:p \
xz:p \
zstd:p
zstd:p \
lz4:p
3 changes: 2 additions & 1 deletion dist/get_deps_tumbleweed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ zypper install \
libzstd-devel \
zlib-devel \
bzip3-devel \
xz-devel
xz-devel \
lz4-dev
12 changes: 6 additions & 6 deletions plugins/decompress/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ add_imhex_plugin(
BZIP2
LIBLZMA
ZSTD
LZ4
)

find_package(ZSTD)
if(ZSTD_FOUND)
set(LIBRARIES ${LIBRARIES} "${ZSTD_LIBRARY}")
message(STATUS "Enabling decompression support using ZSTD (${ZSTD_VERSION})")
enable_plugin_feature(ZSTD)
endif()
set(LIBLZMA_HAS_AUTO_DECODER 1)
set(LIBLZMA_HAS_EASY_ENCODER 1)
set(LIBLZMA_HAS_LZMA_PRESET 1)

addOptionalLibrary(ZLIB ZLIB)
addOptionalLibrary(BZip2 BZip2)
addOptionalLibrary(LibLZMA LibLZMA)
addOptionalLibrary(ZSTD zstd)
addOptionalLibrary(LZ4 lz4)
target_link_libraries(decompress PRIVATE ${LIBRARIES})
56 changes: 52 additions & 4 deletions plugins/decompress/source/content/pl_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
#if IMHEX_FEATURE_ENABLED(ZSTD)
#include <zstd.h>
#endif
#if IMHEX_FEATURE_ENABLED(LZ4)
#include <lz4.h>
#include <lz4frame.h>
#endif


namespace hex::plugin::decompress {

Expand Down Expand Up @@ -89,7 +94,7 @@ namespace hex::plugin::decompress {
return true;
#else
hex::unused(evaluator, params);
err::E0012.throwError("hex::dec::zlib_decompress is not available. Please recompile with zlib support.");
err::E0012.throwError("hex::dec::zlib_decompress is not available. Please recompile ImHex with zlib support.");
#endif
});

Expand Down Expand Up @@ -136,7 +141,7 @@ namespace hex::plugin::decompress {
return true;
#else
hex::unused(evaluator, params);
err::E0012.throwError("hex::dec::bzlib_decompress is not available. Please recompile with bzip2 support.");
err::E0012.throwError("hex::dec::bzlib_decompress is not available. Please recompile ImHex with bzip2 support.");
#endif

});
Expand Down Expand Up @@ -184,7 +189,7 @@ namespace hex::plugin::decompress {
return true;
#else
hex::unused(evaluator, params);
err::E0012.throwError("hex::dec::lzma_decompress is not available. Please recompile with liblzma support.");
err::E0012.throwError("hex::dec::lzma_decompress is not available. Please recompile ImHex with liblzma support.");
#endif
});

Expand Down Expand Up @@ -229,7 +234,50 @@ namespace hex::plugin::decompress {
return true;
#else
hex::unused(evaluator, params);
err::E0012.throwError("hex::dec::zstd_decompress is not available. Please recompile with zstd support.");
err::E0012.throwError("hex::dec::zstd_decompress is not available. Please recompile ImHex with zstd support.");
#endif
});

/* lz4_decompress(compressed_pattern, section_id) */
ContentRegistry::PatternLanguage::addFunction(nsHexDec, "lz4_decompress", FunctionParameterCount::exactly(2), [](Evaluator *evaluator, auto params) -> std::optional<Token::Literal> {
#if IMHEX_FEATURE_ENABLED(LZ4)
auto compressedData = getCompressedData(evaluator, params[0]);
auto &section = evaluator->getSection(params[1].toUnsigned());

// Create the decompression context
LZ4F_decompressionContext_t dctx;
LZ4F_errorCode_t err = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
if (LZ4F_isError(err)) {
return false;
}

std::vector<u8> outBuffer(1024 * 1024);

const u8* sourcePointer = compressedData.data();
size_t srcSize = compressedData.size();

while (srcSize > 0) {
u8* dstPtr = outBuffer.data();
size_t dstCapacity = outBuffer.size();

// Decompress the data
size_t ret = LZ4F_decompress(dctx, dstPtr, &dstCapacity, sourcePointer, &srcSize, nullptr);
if (LZ4F_isError(ret)) {
LZ4F_freeDecompressionContext(dctx);
return false;
}

section.insert(section.end(), outBuffer.begin(), outBuffer.begin() + dstCapacity);
sourcePointer += (compressedData.size() - srcSize);
}

// Free the decompression context
LZ4F_freeDecompressionContext(dctx);

return true;
#else
hex::unused(evaluator, params);
err::E0012.throwError("hex::dec::lz4_decompress is not available. Please recompile ImHex with liblz4 support.");
#endif
});
}
Expand Down

0 comments on commit 1f5e4ce

Please sign in to comment.