diff --git a/.gitmodules b/.gitmodules index 4881782..fdcaafc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "3rdparty/zstd"] path = 3rdparty/zstd url = https://github.com/facebook/zstd +[submodule "3rdparty/lz4"] + path = 3rdparty/lz4 + url = https://github.com/lz4/lz4.git diff --git a/3rdparty/lz4 b/3rdparty/lz4 new file mode 160000 index 0000000..c609c16 --- /dev/null +++ b/3rdparty/lz4 @@ -0,0 +1 @@ +Subproject commit c609c16aed95ed339e142535b1b270e7b9e24ac1 diff --git a/3rdparty/lz4.cmake b/3rdparty/lz4.cmake new file mode 100644 index 0000000..47a1ae5 --- /dev/null +++ b/3rdparty/lz4.cmake @@ -0,0 +1,378 @@ +# CMake support for LZ4 +# +# To the extent possible under law, the author(s) have dedicated all +# copyright and related and neighboring rights to this software to +# the public domain worldwide. This software is distributed without +# any warranty. +# +# For details, see . + + +# Use range version specification for policy control while maintaining +# compatibility with older CMake versions +cmake_minimum_required(VERSION 3.5...4.0.2) + +set(LZ4_BUNDLED_MODE ON) +set(LZ4_TOP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/lz4") + +#----------------------------------------------------------------------------- +# VERSION EXTRACTION - Parse version information from header file +#----------------------------------------------------------------------------- +function(parse_lz4_version VERSION_TYPE) + file(STRINGS "${LZ4_TOP_SOURCE_DIR}/lib/lz4.h" version_line REGEX "^#define LZ4_VERSION_${VERSION_TYPE} +([0-9]+).*$") + string(REGEX REPLACE "^#define LZ4_VERSION_${VERSION_TYPE} +([0-9]+).*$" "\\1" version_number "${version_line}") + set(LZ4_VERSION_${VERSION_TYPE} ${version_number} PARENT_SCOPE) +endfunction() + +foreach(version_type IN ITEMS MAJOR MINOR RELEASE) + parse_lz4_version(${version_type}) +endforeach() + +set(LZ4_VERSION_STRING "${LZ4_VERSION_MAJOR}.${LZ4_VERSION_MINOR}.${LZ4_VERSION_RELEASE}") +mark_as_advanced(LZ4_VERSION_STRING LZ4_VERSION_MAJOR LZ4_VERSION_MINOR LZ4_VERSION_RELEASE) + +message(STATUS "Creating build script for LZ4 version: ${LZ4_VERSION_STRING}") + +project(LZ4 VERSION ${LZ4_VERSION_STRING} LANGUAGES C) + +#----------------------------------------------------------------------------- +# DEFAULT BUILD TYPE - Set Release as default when no build type is specified +#----------------------------------------------------------------------------- +# Set a default build type if none was specified +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +endif() + +#----------------------------------------------------------------------------- +# BUILD OPTIONS - Configure build targets and features +#----------------------------------------------------------------------------- +option(LZ4_BUILD_CLI "Build lz4 program" OFF) +option(LZ4_BUILD_LEGACY_LZ4C "Build lz4c program with legacy argument support" OFF) + + +# Determine if LZ4 is being built as part of another project. +# If LZ4 is bundled in another project, we don't want to install anything. +# Default behavior can be overridden by setting the LZ4_BUNDLED_MODE variable. +if(NOT DEFINED LZ4_BUNDLED_MODE) + get_directory_property(LZ4_IS_SUBPROJECT PARENT_DIRECTORY) + if(LZ4_IS_SUBPROJECT) + set(LZ4_BUNDLED_MODE ON) + else() + set(LZ4_BUNDLED_MODE OFF) + endif() +endif() +mark_as_advanced(LZ4_BUNDLED_MODE) + +#----------------------------------------------------------------------------- +# PACKAGING - CPack configuration +#----------------------------------------------------------------------------- +if(NOT LZ4_BUNDLED_MODE AND NOT CPack_CMake_INCLUDED) + set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LZ4 compression library") + set(CPACK_PACKAGE_DESCRIPTION_FILE "${LZ4_TOP_SOURCE_DIR}/README.md") + set(CPACK_RESOURCE_FILE_LICENSE "${LZ4_TOP_SOURCE_DIR}/LICENSE") + set(CPACK_PACKAGE_VERSION_MAJOR ${LZ4_VERSION_MAJOR}) + set(CPACK_PACKAGE_VERSION_MINOR ${LZ4_VERSION_MINOR}) + set(CPACK_PACKAGE_VERSION_PATCH ${LZ4_VERSION_RELEASE}) + include(CPack) +endif(NOT LZ4_BUNDLED_MODE AND NOT CPack_CMake_INCLUDED) + +#----------------------------------------------------------------------------- +# LIBRARY TYPE CONFIGURATION - Static vs Shared libraries +#----------------------------------------------------------------------------- +# Allow people to choose whether to build shared or static libraries +# via the BUILD_SHARED_LIBS option unless we are in bundled mode, in +# which case we always use static libraries. +include(CMakeDependentOption) +CMAKE_DEPENDENT_OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON "NOT LZ4_BUNDLED_MODE" OFF) +CMAKE_DEPENDENT_OPTION(BUILD_STATIC_LIBS "Build static libraries" OFF "BUILD_SHARED_LIBS" ON) + +if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) + message(FATAL_ERROR "Both BUILD_SHARED_LIBS and BUILD_STATIC_LIBS have been disabled") +endif(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) + +#----------------------------------------------------------------------------- +# SOURCE FILES & DIRECTORIES - Path setup and source file collection +#----------------------------------------------------------------------------- +set(LZ4_LIB_SOURCE_DIR "${LZ4_TOP_SOURCE_DIR}/lib") +set(LZ4_PROG_SOURCE_DIR "${LZ4_TOP_SOURCE_DIR}/programs") + +include_directories("${LZ4_LIB_SOURCE_DIR}") + +# CLI sources +file(GLOB LZ4_SOURCES + "${LZ4_LIB_SOURCE_DIR}/*.c") +file(GLOB LZ4_CLI_SOURCES + "${LZ4_PROG_SOURCE_DIR}/*.c") +list(APPEND LZ4_CLI_SOURCES ${LZ4_SOURCES}) # LZ4_CLI always use liblz4 sources directly. + +#----------------------------------------------------------------------------- +# POSITION INDEPENDENT CODE - PIC settings for static libraries +#----------------------------------------------------------------------------- +# Whether to use position independent code for the static library. If +# we're building a shared library this is ignored and PIC is always +# used. +if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE OR CMAKE_POSITION_INDEPENDENT_CODE) + set(LZ4_POSITION_INDEPENDENT_LIB_DEFAULT ON) +else() + set(LZ4_POSITION_INDEPENDENT_LIB_DEFAULT OFF) +endif(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE OR CMAKE_POSITION_INDEPENDENT_CODE) + +option(LZ4_POSITION_INDEPENDENT_LIB "Use position independent code for static library (if applicable)" ${LZ4_POSITION_INDEPENDENT_LIB_DEFAULT}) + +#----------------------------------------------------------------------------- +# TARGETS - Library and executable targets +#----------------------------------------------------------------------------- +# liblz4 +include(GNUInstallDirs) +set(LZ4_LIBRARIES_BUILT) +if(BUILD_SHARED_LIBS) + add_library(lz4_shared SHARED ${LZ4_SOURCES}) + target_include_directories(lz4_shared + PUBLIC $ + INTERFACE $) + set_target_properties(lz4_shared PROPERTIES + OUTPUT_NAME lz4 + SOVERSION "${LZ4_VERSION_MAJOR}" + VERSION "${LZ4_VERSION_STRING}") + if(MSVC) + target_compile_definitions(lz4_shared PRIVATE + LZ4_DLL_EXPORT=1) + endif(MSVC) + list(APPEND LZ4_LIBRARIES_BUILT lz4_shared) +endif() +if(BUILD_STATIC_LIBS) + set(STATIC_LIB_NAME lz4) + if(MSVC AND BUILD_SHARED_LIBS) + set(STATIC_LIB_NAME lz4_static) + endif(MSVC AND BUILD_SHARED_LIBS) + add_library(lz4_static STATIC ${LZ4_SOURCES}) + target_include_directories(lz4_static + PUBLIC $ + INTERFACE $) + set_target_properties(lz4_static PROPERTIES + OUTPUT_NAME ${STATIC_LIB_NAME} + POSITION_INDEPENDENT_CODE ${LZ4_POSITION_INDEPENDENT_LIB}) + list(APPEND LZ4_LIBRARIES_BUILT lz4_static) +endif() +# Add unified target. +add_library(lz4 INTERFACE) +list(APPEND LZ4_LIBRARIES_BUILT lz4) +if(BUILD_SHARED_LIBS) + target_link_libraries(lz4 INTERFACE lz4_shared) +else() + target_link_libraries(lz4 INTERFACE lz4_static) +endif(BUILD_SHARED_LIBS) + +#----------------------------------------------------------------------------- +# DEBUG CONFIGURATION - Configurable LZ4_DEBUG level +#----------------------------------------------------------------------------- +# LZ4_DEBUG levels: +# 0 - Disable everything (default for Release) +# 1 - Enable assert() statements +# 2-8 - Enable debug traces with increasing verbosity +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LZ4_DEBUG_LEVEL_DEFAULT 1) +else() + set(LZ4_DEBUG_LEVEL_DEFAULT 0) +endif() + +set(LZ4_DEBUG_LEVEL ${LZ4_DEBUG_LEVEL_DEFAULT} CACHE STRING + "LZ4 debug level: 0=disabled, 1=assert(), 2-8=debug traces with increasing verbosity") +set_property(CACHE LZ4_DEBUG_LEVEL PROPERTY STRINGS "0" "1" "2" "3" "4" "5" "6" "7" "8") + +# Apply LZ4_DEBUG configuration if level > 0 +if(LZ4_DEBUG_LEVEL GREATER 0) + if(MSVC) + add_definitions(/DLZ4_DEBUG=${LZ4_DEBUG_LEVEL}) + else() + add_definitions(-DLZ4_DEBUG=${LZ4_DEBUG_LEVEL}) + endif() +endif() + +#----------------------------------------------------------------------------- +# NAMESPACE CONFIGURATION - xxHash namespace settings +#----------------------------------------------------------------------------- +# xxhash namespace +if(BUILD_SHARED_LIBS) + target_compile_definitions(lz4_shared PRIVATE + XXH_NAMESPACE=LZ4_) +endif(BUILD_SHARED_LIBS) +if(BUILD_STATIC_LIBS) + target_compile_definitions(lz4_static PRIVATE + XXH_NAMESPACE=LZ4_) +endif(BUILD_STATIC_LIBS) + +#----------------------------------------------------------------------------- +# CLI EXECUTABLES - Configuring command-line programs +#----------------------------------------------------------------------------- +# lz4 +if(LZ4_BUILD_CLI) + set(LZ4_PROGRAMS_BUILT lz4cli) + add_executable(lz4cli ${LZ4_CLI_SOURCES}) + set_target_properties(lz4cli PROPERTIES OUTPUT_NAME lz4) +endif(LZ4_BUILD_CLI) + +# lz4c +if(LZ4_BUILD_LEGACY_LZ4C) + list(APPEND LZ4_PROGRAMS_BUILT lz4c) + add_executable(lz4c ${LZ4_CLI_SOURCES}) + set_target_properties(lz4c PROPERTIES COMPILE_DEFINITIONS "ENABLE_LZ4C_LEGACY_OPTIONS") +endif(LZ4_BUILD_LEGACY_LZ4C) + +#----------------------------------------------------------------------------- +# COMPILER FLAGS - Configure warning flags and compiler-specific options +#----------------------------------------------------------------------------- +# Extra warning flags - apply only to LZ4 targets, not globally +set(LZ4_WARNING_FLAGS) +if(MSVC) + list(APPEND LZ4_WARNING_FLAGS "/W4") +else() + include(CheckCCompilerFlag) + foreach(flag + # GCC-style + -pedantic-errors + -Wall + -Wextra + -Wundef + -Wcast-qual + -Wcast-align + -Wshadow + -Wswitch-enum + -Wdeclaration-after-statement + -Wstrict-prototypes + -Wpointer-arith) + + # Because https://gcc.gnu.org/wiki/FAQ#wnowarning + string(REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}") + string(REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CFLAG_${flag_to_test}") + + check_c_compiler_flag("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name}) + + if(${test_name}) + list(APPEND LZ4_WARNING_FLAGS "${flag}") + endif() + + unset(test_name) + unset(flag_to_test) + endforeach(flag) +endif(MSVC) + +# Apply warning flags to LZ4 targets only (not globally) +if(BUILD_SHARED_LIBS AND LZ4_WARNING_FLAGS) + target_compile_options(lz4_shared PRIVATE $<$:${LZ4_WARNING_FLAGS}>) +endif() +if(BUILD_STATIC_LIBS AND LZ4_WARNING_FLAGS) + target_compile_options(lz4_static PRIVATE $<$:${LZ4_WARNING_FLAGS}>) +endif() +if(LZ4_BUILD_CLI AND LZ4_WARNING_FLAGS) + target_compile_options(lz4cli PRIVATE $<$:${LZ4_WARNING_FLAGS}>) +endif() +if(LZ4_BUILD_LEGACY_LZ4C AND LZ4_WARNING_FLAGS) + target_compile_options(lz4c PRIVATE $<$:${LZ4_WARNING_FLAGS}>) +endif() + + +#----------------------------------------------------------------------------- +# INSTALLATION - Install targets, headers, and documentation +#----------------------------------------------------------------------------- +if(NOT LZ4_BUNDLED_MODE) + install(TARGETS ${LZ4_PROGRAMS_BUILT} + BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(TARGETS ${LZ4_LIBRARIES_BUILT} + EXPORT lz4Targets + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(FILES + "${LZ4_LIB_SOURCE_DIR}/lz4.h" + "${LZ4_LIB_SOURCE_DIR}/lz4hc.h" + "${LZ4_LIB_SOURCE_DIR}/lz4frame.h" + "${LZ4_LIB_SOURCE_DIR}/lz4file.h" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install(FILES "${LZ4_PROG_SOURCE_DIR}/lz4.1" + DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/liblz4.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + +#----------------------------------------------------------------------------- +# CMAKE PACKAGE CONFIG - Configure CMake package for find_package support +#----------------------------------------------------------------------------- + include(CMakePackageConfigHelpers) + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/lz4ConfigVersion.cmake" + VERSION ${LZ4_VERSION_STRING} + COMPATIBILITY SameMajorVersion) + + set(LZ4_PKG_INSTALLDIR "${CMAKE_INSTALL_LIBDIR}/cmake/lz4") + configure_package_config_file( + "${CMAKE_CURRENT_LIST_DIR}/lz4Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/lz4Config.cmake" + INSTALL_DESTINATION ${LZ4_PKG_INSTALLDIR}) + export(EXPORT lz4Targets + FILE ${CMAKE_CURRENT_BINARY_DIR}/lz4Targets.cmake + NAMESPACE LZ4::) + + install(EXPORT lz4Targets + FILE lz4Targets.cmake + NAMESPACE LZ4:: + DESTINATION ${LZ4_PKG_INSTALLDIR}) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/lz4Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/lz4ConfigVersion.cmake + DESTINATION ${LZ4_PKG_INSTALLDIR}) + +#----------------------------------------------------------------------------- +# SYMLINKS - Create and install Unix symlinks and manpage aliases +#----------------------------------------------------------------------------- + # Install lz4cat and unlz4 symlinks on Unix systems + if(UNIX AND LZ4_BUILD_CLI) + foreach(cli_tool IN ITEMS lz4cat unlz4) + # Create a custom target for the symlink creation + add_custom_target("create_${cli_tool}_symlink" ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink + $ ${cli_tool} + DEPENDS lz4cli + COMMENT "Creating symlink for ${cli_tool}" + VERBATIM) + + # Install the symlink into the binary installation directory + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${cli_tool}" + DESTINATION ${CMAKE_INSTALL_BINDIR} + RENAME ${cli_tool}) + endforeach() + + # create manpage aliases + foreach(f lz4cat unlz4) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${f}.1" ".so man1/lz4.1\n") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${f}.1" + DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") + endforeach() + endif(UNIX AND LZ4_BUILD_CLI) +endif(NOT LZ4_BUNDLED_MODE) + +#----------------------------------------------------------------------------- +# PKG-CONFIG - Generate and install pkg-config file +#----------------------------------------------------------------------------- +# pkg-config +set(PREFIX "${CMAKE_INSTALL_PREFIX}") + +if("${CMAKE_INSTALL_FULL_LIBDIR}" STREQUAL "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + set(LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}") +else() + set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}") +endif("${CMAKE_INSTALL_FULL_LIBDIR}" STREQUAL "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + +if("${CMAKE_INSTALL_FULL_INCLUDEDIR}" STREQUAL "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") + set(INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") +else() + set(INCLUDEDIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}") +endif("${CMAKE_INSTALL_FULL_INCLUDEDIR}" STREQUAL "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") + +# for liblz4.pc substitution +set(VERSION ${LZ4_VERSION_STRING}) +configure_file(${LZ4_LIB_SOURCE_DIR}/liblz4.pc.in liblz4.pc @ONLY) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 93ae276..7a94bc9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,7 @@ add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h a include(3rdparty/bzip2.cmake) include(3rdparty/flac.cmake) +include(3rdparty/lz4.cmake) include(3rdparty/lzfse.cmake) include(3rdparty/lzip.cmake) include(3rdparty/lzma.cmake) @@ -169,7 +170,7 @@ macro(target_link_libraries_whole_archive target) endif() endmacro() -target_link_libraries_whole_archive("Aaru.Compression.Native" libzstd_static m) +target_link_libraries_whole_archive("Aaru.Compression.Native" libzstd_static lz4_static m) check_include_file("semaphore.h" HAVE_SEMAPHORE_H) diff --git a/README.md b/README.md index 3613cbe..6f06b04 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Currently implemented algorithms are: - Apple RLE (Run Length Encoding created for Apple DART) - [BZIP2](https://gitlab.com/bzip2/bzip2.git) - [FLAC](https://github.com/xiph/flac) +- [LZ4](https://github.com/lz4/lz4) - [LZFSE](https://github.com/lzfse/lzfse) - [LZIP](http://www.nongnu.org/lzip) - [LZMA](https://www.7-zip.org) diff --git a/library.c b/library.c index 3a970fe..c62c9c7 100644 --- a/library.c +++ b/library.c @@ -21,6 +21,7 @@ #include "library.h" #include "3rdparty/bzip2/bzlib.h" +#include "3rdparty/lz4/lib/lz4.h" #include "3rdparty/lzfse/src/lzfse.h" #include "3rdparty/lzma/C/LzmaLib.h" #include "3rdparty/zstd/lib/zstd.h" @@ -38,6 +39,18 @@ AARU_EXPORT int32_t AARU_CALL AARU_bzip2_encode_buffer(uint8_t *dst_buffer, uint return BZ2_bzBuffToBuffCompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, blockSize100k, 0, 0); } +AARU_EXPORT int32_t AARU_CALL AARU_lz4_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer, + int32_t src_size) +{ + return LZ4_decompress_safe((const char *)src_buffer, (char *)dst_buffer, src_size, dst_size); +} + +AARU_EXPORT int32_t AARU_CALL AARU_lz4_encode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer, + int32_t src_size) +{ + return LZ4_compress_default((const char *)src_buffer, (char *)dst_buffer, src_size, dst_size); +} + AARU_EXPORT size_t AARU_CALL AARU_lzfse_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size, void *scratch_buffer) { diff --git a/library.h b/library.h index 92cda9b..3ba6047 100644 --- a/library.h +++ b/library.h @@ -70,6 +70,12 @@ AARU_EXPORT size_t AARU_CALL AARU_flac_encode_redbook_buffer( uint32_t min_residual_partition_order, uint32_t max_residual_partition_order, const char *application_id, uint32_t application_id_len); +AARU_EXPORT int32_t AARU_CALL AARU_lz4_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer, + int32_t src_size); + +AARU_EXPORT int32_t AARU_CALL AARU_lz4_encode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer, + int32_t src_size); + AARU_EXPORT int32_t AARU_CALL AARU_lzip_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer, int32_t src_size); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1ed61b8..836e6fc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,6 +27,9 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lzfse.bin file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/zstd.zst DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lz4.bin + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lzma.bin DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) @@ -74,7 +77,7 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/ha_hsc.bin # 'Google_Tests_run' is the target name # 'test1.cpp tests2.cpp' are source files with tests -add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp flac.cpp +add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp flac.cpp lz4.cpp zoo/lzd.cpp arc/pack.cpp lh5.cpp arc/squeeze.cpp arc/crunch.cpp arc/squash.cpp pak/crush.cpp pak/distill.cpp ha.cpp) target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native") diff --git a/tests/data/lz4.bin b/tests/data/lz4.bin new file mode 100644 index 0000000..75cae17 Binary files /dev/null and b/tests/data/lz4.bin differ diff --git a/tests/lz4.cpp b/tests/lz4.cpp new file mode 100644 index 0000000..347886f --- /dev/null +++ b/tests/lz4.cpp @@ -0,0 +1,138 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2025 Natalia Portillo. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "../library.h" +#include "crc32.h" +#include "gtest/gtest.h" + +#define EXPECTED_CRC32 0x954bf76e // CRC32 of whole 8MB data.bin file + +static const uint8_t *buffer; +static int32_t buffer_size; + +class lz4Fixture : public ::testing::Test +{ +public: + lz4Fixture() + { + // initialization; + // can also be done in SetUp() + } + +protected: + void SetUp() + { + char path[PATH_MAX]; + char filename[PATH_MAX]; + + getcwd(path, PATH_MAX); + snprintf(filename, PATH_MAX, "%s/data/lz4.bin", path); + + FILE *file = fopen(filename, "rb"); + fseek(file, 0, SEEK_END); + buffer_size = ftell(file); + fseek(file, 0, SEEK_SET); + buffer = (const uint8_t *)malloc(buffer_size); + fread((void *)buffer, 1, buffer_size, file); + fclose(file); + } + + void TearDown() { free((void *)buffer); } + + ~lz4Fixture() + { + // resources cleanup, no exceptions allowed + } + + // shared user data +}; + +TEST_F(lz4Fixture, lz4) +{ + int32_t original_len = 8388608; // 8MB + auto *outBuf = (uint8_t *)malloc(original_len); + + auto decoded = AARU_lz4_decode_buffer(outBuf, original_len, buffer, buffer_size); + + EXPECT_GT(decoded, 0); + EXPECT_EQ(decoded, original_len); + + auto crc = crc32_data(outBuf, original_len); + + free(outBuf); + + EXPECT_EQ(crc, EXPECTED_CRC32); +} + +TEST_F(lz4Fixture, lz4Compress) +{ + int32_t original_len = 8388608; + int32_t cmp_len = original_len; + int32_t decmp_len = original_len; + char path[PATH_MAX]; + char filename[PATH_MAX * 2]; + FILE *file; + uint32_t original_crc, decmp_crc; + const uint8_t *original; + uint8_t *cmp_buffer; + uint8_t *decmp_buffer; + int32_t newSize; + + // Allocate buffers + original = (const uint8_t *)malloc(original_len); + cmp_buffer = (uint8_t *)malloc(cmp_len); + decmp_buffer = (uint8_t *)malloc(decmp_len); + + // Read the file + getcwd(path, PATH_MAX); + snprintf(filename, PATH_MAX, "%s/data/data.bin", path); + + file = fopen(filename, "rb"); + fread((void *)original, 1, original_len, file); + fclose(file); + + // Calculate the CRC + original_crc = crc32_data(original, original_len); + + // Compress + newSize = AARU_lz4_encode_buffer(cmp_buffer, cmp_len, original, original_len); + EXPECT_GT(newSize, 0); + cmp_len = newSize; + + // Decompress + newSize = AARU_lz4_decode_buffer(decmp_buffer, decmp_len, cmp_buffer, cmp_len); + EXPECT_GT(newSize, 0); + decmp_len = newSize; + + EXPECT_EQ(decmp_len, original_len); + + decmp_crc = crc32_data(decmp_buffer, decmp_len); + + // Free buffers + free((void *)original); + free(cmp_buffer); + free(decmp_buffer); + + EXPECT_EQ(decmp_crc, original_crc); +}