diff --git a/.gitignore b/.gitignore index 1e544a8b..d0670fc6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ main.exe Benchmark*.txt* Benchmark/Files/*.compressed.* Benchmark/Files/*.decompressed.* +Benchmark/Files/*.zipped.* +Benchmark/Files/*.unzipped.* # Test generated files Test*.txt* diff --git a/.vscode/settings.json b/.vscode/settings.json index 3ff191a1..a7083fa8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -19,6 +19,25 @@ "inflate_zlib.h": "c", "unity.h": "c", "raiistring.h": "c", - "fileutils.h": "c" + "fileutils.h": "c", + "zip_minizip.h": "c", + "unzip.h": "c", + "unzip_minizip.h": "c", + "testzipunzipminizip.h": "c", + "unity_fixture.h": "c", + "testdeflateinflatezlib.h": "c", + "stdbool.h": "c", + "cstdlib": "c", + "rope": "c", + "*.def": "c", + "string.h": "c", + "testunzipminizip.h": "c", + "unity_fixture_internals.h": "c", + "unity_memory.h": "c", + "string_view": "c", + "regex": "c", + "*.inc": "c", + "bitset": "c", + "zipcontentinfo.h": "c" }, } \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirFileOne/TextFileOne_store.txt b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirFileOne/TextFileOne_store.txt new file mode 100644 index 00000000..596bd08b --- /dev/null +++ b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirFileOne/TextFileOne_store.txt @@ -0,0 +1,2 @@ +This is +the first text file. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirFileTwo/TextFileTwo_store.txt b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirFileTwo/TextFileTwo_store.txt new file mode 100644 index 00000000..81582c29 --- /dev/null +++ b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirFileTwo/TextFileTwo_store.txt @@ -0,0 +1,2 @@ +Second file is this +. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirOfDirs/OtherDir/FilleInDirectory.txt b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirOfDirs/OtherDir/FilleInDirectory.txt new file mode 100644 index 00000000..aefc10b2 --- /dev/null +++ b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirOfDirs/OtherDir/FilleInDirectory.txt @@ -0,0 +1 @@ +This file is in a directory \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirOfDirs/SubDirWithCopyOfTopLevelFile/TextFile_store.txt b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirOfDirs/SubDirWithCopyOfTopLevelFile/TextFile_store.txt new file mode 100644 index 00000000..63123b36 --- /dev/null +++ b/Benchmark/Files/MultiTextFileAndSubDirZip_store/DirOfDirs/SubDirWithCopyOfTopLevelFile/TextFile_store.txt @@ -0,0 +1,3 @@ +The 3rd file contains + +an empty line on line 2. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileAndSubDirZip_store/MultiTextFileAndSubDirZip_store.zip b/Benchmark/Files/MultiTextFileAndSubDirZip_store/MultiTextFileAndSubDirZip_store.zip new file mode 100644 index 00000000..4cf4a0ed Binary files /dev/null and b/Benchmark/Files/MultiTextFileAndSubDirZip_store/MultiTextFileAndSubDirZip_store.zip differ diff --git a/Benchmark/Files/MultiTextFileAndSubDirZip_store/Readme.md b/Benchmark/Files/MultiTextFileAndSubDirZip_store/Readme.md new file mode 100644 index 00000000..cf67ab6c --- /dev/null +++ b/Benchmark/Files/MultiTextFileAndSubDirZip_store/Readme.md @@ -0,0 +1 @@ +The zip file has been created with 7zip and using deflate compression level `store` to not compress the files. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileAndSubDirZip_store/TextFile_store.txt b/Benchmark/Files/MultiTextFileAndSubDirZip_store/TextFile_store.txt new file mode 100644 index 00000000..63123b36 --- /dev/null +++ b/Benchmark/Files/MultiTextFileAndSubDirZip_store/TextFile_store.txt @@ -0,0 +1,3 @@ +The 3rd file contains + +an empty line on line 2. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileZip_store/MultiTextFileZip_store.zip b/Benchmark/Files/MultiTextFileZip_store/MultiTextFileZip_store.zip new file mode 100644 index 00000000..6f96d621 Binary files /dev/null and b/Benchmark/Files/MultiTextFileZip_store/MultiTextFileZip_store.zip differ diff --git a/Benchmark/Files/MultiTextFileZip_store/Readme.md b/Benchmark/Files/MultiTextFileZip_store/Readme.md new file mode 100644 index 00000000..cf67ab6c --- /dev/null +++ b/Benchmark/Files/MultiTextFileZip_store/Readme.md @@ -0,0 +1 @@ +The zip file has been created with 7zip and using deflate compression level `store` to not compress the files. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileZip_store/TextFileOne_store.txt b/Benchmark/Files/MultiTextFileZip_store/TextFileOne_store.txt new file mode 100644 index 00000000..596bd08b --- /dev/null +++ b/Benchmark/Files/MultiTextFileZip_store/TextFileOne_store.txt @@ -0,0 +1,2 @@ +This is +the first text file. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileZip_store/TextFileOne_store.unzipped.txt b/Benchmark/Files/MultiTextFileZip_store/TextFileOne_store.unzipped.txt new file mode 100644 index 00000000..e69de29b diff --git a/Benchmark/Files/MultiTextFileZip_store/TextFileTwo_store.txt b/Benchmark/Files/MultiTextFileZip_store/TextFileTwo_store.txt new file mode 100644 index 00000000..81582c29 --- /dev/null +++ b/Benchmark/Files/MultiTextFileZip_store/TextFileTwo_store.txt @@ -0,0 +1,2 @@ +Second file is this +. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileZip_store/TextFileTwo_store.unzipped.txt b/Benchmark/Files/MultiTextFileZip_store/TextFileTwo_store.unzipped.txt new file mode 100644 index 00000000..e69de29b diff --git a/Benchmark/Files/MultiTextFileZip_store/ThirdTextFile_store.txt b/Benchmark/Files/MultiTextFileZip_store/ThirdTextFile_store.txt new file mode 100644 index 00000000..63123b36 --- /dev/null +++ b/Benchmark/Files/MultiTextFileZip_store/ThirdTextFile_store.txt @@ -0,0 +1,3 @@ +The 3rd file contains + +an empty line on line 2. \ No newline at end of file diff --git a/Benchmark/Files/MultiTextFileZip_store/ThirdTextFile_store.unzipped.txt b/Benchmark/Files/MultiTextFileZip_store/ThirdTextFile_store.unzipped.txt new file mode 100644 index 00000000..e69de29b diff --git a/Benchmark/Files/SmallBasicTextFileZip_store/Readme.md b/Benchmark/Files/SmallBasicTextFileZip_store/Readme.md new file mode 100644 index 00000000..ef9bb4c5 --- /dev/null +++ b/Benchmark/Files/SmallBasicTextFileZip_store/Readme.md @@ -0,0 +1 @@ +The zip file has been created with 7zip and using deflate compression level `store` to not compress the file. \ No newline at end of file diff --git a/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.txt b/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.txt new file mode 100644 index 00000000..81365b1a --- /dev/null +++ b/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.txt @@ -0,0 +1,4 @@ +This is a test file. +On the second line there are eight words + The third line has a tab. +And the last line is a longer piece. Consising of two sentences. \ No newline at end of file diff --git a/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.unzipped.txt b/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.unzipped.txt new file mode 100644 index 00000000..e69de29b diff --git a/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.zip b/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.zip new file mode 100644 index 00000000..400668f5 Binary files /dev/null and b/Benchmark/Files/SmallBasicTextFileZip_store/SmallBasicTextFile_store.zip differ diff --git a/CoDeLib/CMakeLists.txt b/CoDeLib/CMakeLists.txt index 11ba318f..d381644b 100644 --- a/CoDeLib/CMakeLists.txt +++ b/CoDeLib/CMakeLists.txt @@ -19,16 +19,21 @@ set(CoDeLib_PUBLIC_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include/CoDeLib) set(COMMON_HEADERS ${CoDeLib_PUBLIC_INCLUDE_PATH}/IDeflate.h ${CoDeLib_PUBLIC_INCLUDE_PATH}/IInflate.h + ${CoDeLib_PUBLIC_INCLUDE_PATH}/IZip.h + ${CoDeLib_PUBLIC_INCLUDE_PATH}/IUnZip.h ) install(FILES ${COMMON_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/CoDeLib) add_subdirectory(Deflate_zlib) add_subdirectory(Inflate_zlib) +add_subdirectory(Zip_minizip) +add_subdirectory(UnZip_minizip) add_subdirectory(RaiiString) +add_subdirectory(ZipContentInfo) add_subdirectory(Test) install( - TARGETS CoDeLib Deflate_zlib Inflate_zlib RaiiString Utility + TARGETS CoDeLib Deflate_zlib Inflate_zlib Zip_minizip UnZip_minizip RaiiString ZipContentInfo Utility EXPORT CoDeLibTargets INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/CoDeLib/Config.cmake.in b/CoDeLib/Config.cmake.in index 5d530219..3adaf2f3 100644 --- a/CoDeLib/Config.cmake.in +++ b/CoDeLib/Config.cmake.in @@ -7,4 +7,6 @@ check_required_components(CoDeLib) include(CMakeFindDependencyMacro) set(ZLIB_USE_STATIC_LIBS "ON") -find_dependency(ZLIB REQUIRED) \ No newline at end of file +find_dependency(ZLIB REQUIRED) + +find_dependency(minizip REQUIRED) \ No newline at end of file diff --git a/CoDeLib/CustomDeflate.md b/CoDeLib/CustomDeflate.md index 1f6a2277..ab327d3b 100644 --- a/CoDeLib/CustomDeflate.md +++ b/CoDeLib/CustomDeflate.md @@ -4,4 +4,5 @@ # refs -- https://pnrsolution.org/Datacenter/Vol4/Issue1/58.pdf \ No newline at end of file +- https://pnrsolution.org/Datacenter/Vol4/Issue1/58.pdf +- https://nachtimwald.com/2019/09/08/making-minizip-easier-to-use/ \ No newline at end of file diff --git a/CoDeLib/Deflate_zlib/CMakeLists.txt b/CoDeLib/Deflate_zlib/CMakeLists.txt index 1175f1a5..86654718 100644 --- a/CoDeLib/Deflate_zlib/CMakeLists.txt +++ b/CoDeLib/Deflate_zlib/CMakeLists.txt @@ -10,7 +10,6 @@ set(ZLIB_USE_STATIC_LIBS "ON") find_package(ZLIB REQUIRED) target_link_libraries(Deflate_zlib PRIVATE ZLIB::ZLIB) -message(STATUS "CoDeLib_PUBLIC_INCLUDE_PATH: ${CoDeLib_PUBLIC_INCLUDE_PATH}") set(Deflate_zlib_PUBLIC_INCLUDE_PATH ${CoDeLib_PUBLIC_INCLUDE_PATH}/Deflate_zlib) set(Deflate_zlib_PUBLIC_HEADERS ${Deflate_zlib_PUBLIC_INCLUDE_PATH}/Deflate_zlib.h diff --git a/CoDeLib/RaiiString/src/RaiiString.c b/CoDeLib/RaiiString/src/RaiiString.c index 479aee3a..89636471 100644 --- a/CoDeLib/RaiiString/src/RaiiString.c +++ b/CoDeLib/RaiiString/src/RaiiString.c @@ -42,4 +42,4 @@ void RaiiStringClean(RaiiString *pThis) { pThis->pString = NULL; } pThis->lengthWithTermination = 0; -} \ No newline at end of file +} diff --git a/CoDeLib/Test/CMakeLists.txt b/CoDeLib/Test/CMakeLists.txt index 57e52e61..28873a53 100644 --- a/CoDeLib/Test/CMakeLists.txt +++ b/CoDeLib/Test/CMakeLists.txt @@ -1,16 +1,15 @@ add_executable(CoDeLib_Test src/main.c src/TestRaiiString.c - src/TestDeflateInflateZlib.c) + src/TestDeflateInflateZlib.c + src/TestUnZipMinizip.c + src/TestZipContentInfo.c +) target_include_directories(CoDeLib_Test PUBLIC $ ) -target_link_libraries(CoDeLib_Test PRIVATE Deflate_zlib) -target_link_libraries(CoDeLib_Test PRIVATE Inflate_zlib) -target_link_libraries(CoDeLib_Test PRIVATE RaiiString) - FetchContent_Declare( Unity GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity.git @@ -21,7 +20,17 @@ FetchContent_Declare( # If cache is not used, you will get `Policy CMP0077 is not set: option() honors normal variables.` set(UNITY_EXTENSION_FIXTURE ON CACHE INTERNAL "") FetchContent_MakeAvailable(Unity) -target_link_libraries(CoDeLib_Test PRIVATE unity) add_subdirectory(Utility) target_link_libraries(CoDeLib_Test PUBLIC Utility) + +target_link_libraries(CoDeLib_Test PRIVATE Deflate_zlib) +target_link_libraries(CoDeLib_Test PRIVATE Inflate_zlib) +target_link_libraries(CoDeLib_Test PRIVATE Zip_minizip) +target_link_libraries(CoDeLib_Test PRIVATE UnZip_minizip) +target_link_libraries(CoDeLib_Test PRIVATE RaiiString) +target_link_libraries(CoDeLib_Test PRIVATE ZipContentInfo) + +target_link_libraries(CoDeLib_Test PRIVATE unity) + + diff --git a/CoDeLib/Test/src/TestDeflateInflateZlib.c b/CoDeLib/Test/src/TestDeflateInflateZlib.c index ad12dce0..fe902e59 100644 --- a/CoDeLib/Test/src/TestDeflateInflateZlib.c +++ b/CoDeLib/Test/src/TestDeflateInflateZlib.c @@ -55,4 +55,4 @@ TEST(TestDeflateInflateZlib, test_InflateZlibWorkWithDeflateZlib) { TEST_GROUP_RUNNER(TestDeflateInflateZlib) { RUN_TEST_CASE(TestDeflateInflateZlib, test_InflateZlibWorkWithDeflateZlib); -} \ No newline at end of file +} diff --git a/CoDeLib/Test/src/TestRaiiString.c b/CoDeLib/Test/src/TestRaiiString.c index 5bb464ee..dc717949 100644 --- a/CoDeLib/Test/src/TestRaiiString.c +++ b/CoDeLib/Test/src/TestRaiiString.c @@ -172,4 +172,4 @@ TEST_GROUP_RUNNER(TestRaiiString) { // RaiiStringClean() RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsNullptrInObject); RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsLengthZeroInObject); -} \ No newline at end of file +} diff --git a/CoDeLib/Test/src/TestUnZipMinizip.c b/CoDeLib/Test/src/TestUnZipMinizip.c new file mode 100644 index 00000000..e0cb275d --- /dev/null +++ b/CoDeLib/Test/src/TestUnZipMinizip.c @@ -0,0 +1,88 @@ +#include "unity_fixture.h" +#include +#include +#include +#include +#include +#include + +static char *g_pFullPathToBenchmarkTestFiles = NULL; + +void SetupTestUnZipMinizip(char *pFullPathToBenchmarkTestFiles) { + g_pFullPathToBenchmarkTestFiles = pFullPathToBenchmarkTestFiles; +} + +TEST_GROUP(TestUnZipMinizip); + +TEST_SETUP(TestUnZipMinizip) { + // Nothing +} + +TEST_TEAR_DOWN(TestUnZipMinizip) { + // Nothing +} + +TEST(TestUnZipMinizip, test_UnZipMinizip_UnZipsSingleFileCorrectly) { + TEST_IGNORE_MESSAGE("In progress"); + + FILE *pInFile = NULL; + FILE *pUnZippedFile = NULL; + FILE *pReferenceUnZippedFile = NULL; + + OpenFile(&pInFile, g_pFullPathToBenchmarkTestFiles, + "/SmallBasicTextFileZip_store/SmallBasicTextFile_store.zip", "r"); + OpenFile( + &pUnZippedFile, g_pFullPathToBenchmarkTestFiles, + "/SmallBasicTextFileZip_store/SmallBasicTextFile_store.unzipped.txt", + "w+"); + OpenFile(&pReferenceUnZippedFile, g_pFullPathToBenchmarkTestFiles, + "/SmallBasicTextFileZip_store/SmallBasicTextFile_store.txt", "r"); + + TEST_ASSERT(FilesAreEqual(pUnZippedFile, pReferenceUnZippedFile)); + fclose(pInFile); + fclose(pUnZippedFile); + fclose(pReferenceUnZippedFile); +} + +TEST(TestUnZipMinizip, test_UnZipMinizip_UnZipsMultipleFilesCorrectly) { + TEST_IGNORE_MESSAGE("In progress"); + + FILE *pInFile = NULL; + FILE *pUnZippedFiles[] = {NULL, NULL, NULL}; + FILE *pReferenceUnZippedFiles[] = {NULL, NULL, NULL}; + const size_t fileCount = 3; + + OpenFile(&pInFile, g_pFullPathToBenchmarkTestFiles, + "/MultiTextFileZip_store/MultiTextFileZip_store.zip", "r"); + // Output files + OpenFile(&pUnZippedFiles[0], g_pFullPathToBenchmarkTestFiles, + "/MultiTextFileZip_store/TextFileOne_store.unzipped.txt", "w+"); + OpenFile(&pUnZippedFiles[1], g_pFullPathToBenchmarkTestFiles, + "/MultiTextFileZip_store/TextFileTwo_store.unzipped.txt", "w+"); + OpenFile(&pUnZippedFiles[2], g_pFullPathToBenchmarkTestFiles, + "/MultiTextFileZip_store/ThirdTextFile_store.unzipped.txt", "w+"); + // Reference files + OpenFile(&pReferenceUnZippedFiles[0], g_pFullPathToBenchmarkTestFiles, + "/MultiTextFileZip_store/TextFileOne_store.txt", "r"); + OpenFile(&pReferenceUnZippedFiles[1], g_pFullPathToBenchmarkTestFiles, + "/MultiTextFileZip_store/TextFileTwo_store.txt", "r"); + OpenFile(&pReferenceUnZippedFiles[2], g_pFullPathToBenchmarkTestFiles, + "/MultiTextFileZip_store/ThirdTextFile_store.txt", "r"); + + for (size_t i = 0; i < fileCount; ++i) { + TEST_ASSERT( + FilesAreEqual(pUnZippedFiles[i], pReferenceUnZippedFiles[i])); + } + fclose(pInFile); + for (size_t i = 0; i < fileCount; ++i) { + fclose(pUnZippedFiles[i]); + fclose(pReferenceUnZippedFiles[i]); + } +} + +TEST_GROUP_RUNNER(TestUnZipMinizip) { + RUN_TEST_CASE(TestUnZipMinizip, + test_UnZipMinizip_UnZipsSingleFileCorrectly); + RUN_TEST_CASE(TestUnZipMinizip, + test_UnZipMinizip_UnZipsMultipleFilesCorrectly); +} diff --git a/CoDeLib/Test/src/TestUnZipMinizip.h b/CoDeLib/Test/src/TestUnZipMinizip.h new file mode 100644 index 00000000..3853d9bd --- /dev/null +++ b/CoDeLib/Test/src/TestUnZipMinizip.h @@ -0,0 +1,3 @@ +#pragma once + +void SetupTestUnZipMinizip(char *pFullPathToBenchmarkTestFiles); \ No newline at end of file diff --git a/CoDeLib/Test/src/TestZipContentInfo.c b/CoDeLib/Test/src/TestZipContentInfo.c new file mode 100644 index 00000000..445c7429 --- /dev/null +++ b/CoDeLib/Test/src/TestZipContentInfo.c @@ -0,0 +1,68 @@ +#include "unity_fixture.h" +#include +#include +#include + +TEST_GROUP(TestZipContentInfo); + +static ZipContentInfo zipContentInfo; + +TEST_SETUP(TestZipContentInfo) {} + +TEST_TEAR_DOWN(TestZipContentInfo) { ZipContentInfoClean(&zipContentInfo); } + +//============================== +// ZipContentInfoClean() +//============================== + +TEST( + TestZipContentInfo, + test_ZipContentInfoClean_SetsZipFileNameToNullptrIfThereIsNoFileNameArray) { + + zipContentInfo = + (ZipContentInfo){.name = RaiiStringCreateFromCString("myZip.zip"), + .pFileArray = NULL, + .fileCount = 0}; + + ZipContentInfoClean(&zipContentInfo); + + TEST_ASSERT_NULL(zipContentInfo.name.pString); + TEST_ASSERT_NULL(zipContentInfo.pFileArray); + TEST_ASSERT_EQUAL(0, zipContentInfo.fileCount); +} + +TEST(TestZipContentInfo, test_ZipContentInfoClean_CleansAllFileNamesInArray) { + + RaiiString fileNames[] = { + RaiiStringCreateFromCString("file1.txt"), + RaiiStringCreateFromCString("SomeDir/file2.txt"), + RaiiStringCreateFromCString("file3.txt"), + }; + zipContentInfo = + (ZipContentInfo){.name = RaiiStringCreateFromCString("myZip.zip"), + .pFileArray = &fileNames[0], + .fileCount = 3}; + + ZipContentInfoClean(&zipContentInfo); + + TEST_ASSERT_NULL(zipContentInfo.name.pString); + TEST_ASSERT_NULL(zipContentInfo.pFileArray); + TEST_ASSERT_EQUAL(0, zipContentInfo.fileCount); + + for (size_t i = 0; i < 3; i++) { + TEST_ASSERT_NULL(fileNames[i].pString); + } +} + +//============================== +// TEST_GROUP_RUNNER +//============================== + +TEST_GROUP_RUNNER(TestZipContentInfo) { + // ZipContentInfoClean() + RUN_TEST_CASE( + TestZipContentInfo, + test_ZipContentInfoClean_SetsZipFileNameToNullptrIfThereIsNoFileNameArray); + RUN_TEST_CASE(TestZipContentInfo, + test_ZipContentInfoClean_CleansAllFileNamesInArray); +} \ No newline at end of file diff --git a/CoDeLib/Test/src/main.c b/CoDeLib/Test/src/main.c index 79fc7503..229d4548 100644 --- a/CoDeLib/Test/src/main.c +++ b/CoDeLib/Test/src/main.c @@ -1,11 +1,14 @@ #include "unity_fixture.h" #include "TestDeflateInflateZlib.h" +#include "TestUnZipMinizip.h" #include static void RunAllTests(void) { RUN_TEST_GROUP(TestRaiiString); RUN_TEST_GROUP(TestDeflateInflateZlib); + RUN_TEST_GROUP(TestUnZipMinizip); + RUN_TEST_GROUP(TestZipContentInfo); } int main(int argc, const char **argv) { @@ -21,6 +24,7 @@ int main(int argc, const char **argv) { } SetupTestDeflateInflateZlib(fullPathToBenchmarkTestFiles.pString); + SetupTestUnZipMinizip(fullPathToBenchmarkTestFiles.pString); return UnityMain(argc, argv, RunAllTests); } diff --git a/CoDeLib/UnZip_minizip/CMakeLists.txt b/CoDeLib/UnZip_minizip/CMakeLists.txt new file mode 100644 index 00000000..c108b40e --- /dev/null +++ b/CoDeLib/UnZip_minizip/CMakeLists.txt @@ -0,0 +1,16 @@ +add_library(UnZip_minizip STATIC + src/UnZip_minizip.c) + +target_include_directories(UnZip_minizip PUBLIC + $ + $ +) + +find_package(MINIZIP REQUIRED) +target_link_libraries(UnZip_minizip PRIVATE MINIZIP::minizip) + +set(UnZip_minizip_PUBLIC_INCLUDE_PATH ${CoDeLib_PUBLIC_INCLUDE_PATH}/UnZip_minizip) +set(UnZip_minizip_PUBLIC_HEADERS + ${UnZip_minizip_PUBLIC_INCLUDE_PATH}/UnZip_minizip.h +) +install(FILES ${UnZip_minizip_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/CoDeLib/UnZip_minizip) diff --git a/CoDeLib/UnZip_minizip/src/UnZip_minizip.c b/CoDeLib/UnZip_minizip/src/UnZip_minizip.c new file mode 100644 index 00000000..41ef4df8 --- /dev/null +++ b/CoDeLib/UnZip_minizip/src/UnZip_minizip.c @@ -0,0 +1,17 @@ +#include + +#include // minizip + +UNZIP_RETURN_CODES UnZip(ZipContentInfo *const pZipInfo + __attribute__((unused))) { + + // TODO: Dummy code to test if it compiles and links + if (UNZ_OK) { + return UNZIP_SUCCESS; + } + return UNZIP_ERROR; +} + +const struct IUnZip unzip_minizip = { + .UnZip = UnZip, +}; diff --git a/CoDeLib/ZipContentInfo/CMakeLists.txt b/CoDeLib/ZipContentInfo/CMakeLists.txt new file mode 100644 index 00000000..58b1f797 --- /dev/null +++ b/CoDeLib/ZipContentInfo/CMakeLists.txt @@ -0,0 +1,14 @@ + +add_library(ZipContentInfo STATIC + src/ZipContentInfo.c) + +target_include_directories(ZipContentInfo PUBLIC + $ + $ +) + +set(ZipContentInfo_PUBLIC_INCLUDE_PATH ${CoDeLib_PUBLIC_INCLUDE_PATH}/ZipContentInfo) +set(ZipContentInfo_PUBLIC_HEADERS + ${ZipContentInfo_PUBLIC_INCLUDE_PATH}/ZipContentInfo.h +) +install(FILES ${ZipContentInfo_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/CoDeLib/ZipContentInfo) diff --git a/CoDeLib/ZipContentInfo/src/ZipContentInfo.c b/CoDeLib/ZipContentInfo/src/ZipContentInfo.c new file mode 100644 index 00000000..47d2782c --- /dev/null +++ b/CoDeLib/ZipContentInfo/src/ZipContentInfo.c @@ -0,0 +1,19 @@ +#include + +void ZipContentInfoClean(ZipContentInfo *pZipInfo) { + if (pZipInfo == NULL) { + return; + } + + RaiiStringClean(&pZipInfo->name); + + for (size_t i = 0; i < pZipInfo->fileCount; i++) { + RaiiStringClean(&pZipInfo->pFileArray[i]); + } + + pZipInfo->fileCount = 0; + + if (pZipInfo->pFileArray != NULL) { + pZipInfo->pFileArray = NULL; + } +} \ No newline at end of file diff --git a/CoDeLib/Zip_minizip/CMakeLists.txt b/CoDeLib/Zip_minizip/CMakeLists.txt new file mode 100644 index 00000000..01a53c21 --- /dev/null +++ b/CoDeLib/Zip_minizip/CMakeLists.txt @@ -0,0 +1,16 @@ +add_library(Zip_minizip STATIC + src/Zip_minizip.c) + +target_include_directories(Zip_minizip PUBLIC + $ + $ +) + +find_package(MINIZIP REQUIRED) +target_link_libraries(Zip_minizip PRIVATE MINIZIP::minizip) + +set(Zip_minizip_PUBLIC_INCLUDE_PATH ${CoDeLib_PUBLIC_INCLUDE_PATH}/Zip_minizip) +set(Zip_minizip_PUBLIC_HEADERS + ${Zip_minizip_PUBLIC_INCLUDE_PATH}/Zip_minizip.h +) +install(FILES ${Zip_minizip_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/CoDeLib/Zip_minizip) diff --git a/CoDeLib/Zip_minizip/src/Zip_minizip.c b/CoDeLib/Zip_minizip/src/Zip_minizip.c new file mode 100644 index 00000000..6524ec84 --- /dev/null +++ b/CoDeLib/Zip_minizip/src/Zip_minizip.c @@ -0,0 +1,17 @@ +#include + +#include // minizip + +ZIP_RETURN_CODES Zip(const ZipContentInfo *const pZipInfo + __attribute__((unused))) { + + // TODO: Dummy code to test if it compiles and links + if (ZIP_OK) { + return ZIP_SUCCESS; + } + return ZIP_ERROR; +} + +const struct IZip zip_minizip = { + .Zip = Zip, +}; diff --git a/CoDeLib/include/CoDeLib/IUnZip.h b/CoDeLib/include/CoDeLib/IUnZip.h new file mode 100644 index 00000000..7adf990a --- /dev/null +++ b/CoDeLib/include/CoDeLib/IUnZip.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +typedef enum { UNZIP_SUCCESS, UNZIP_ERROR } UNZIP_RETURN_CODES; + +struct IUnZip { + /*! + * @brief Un-zips the input zip file and writes the output to the output + * files. + * @param pZipInfo The information about the zip file. The filenames in + * pZipInfo will be filled by the unzipping function. The caller is + * responsible for cleaning up the provided pZipInfo pointer. + * @return UNZIP_SUCCESS if the un-zipping was successful, UNZIP_ERROR + * otherwise. + */ + UNZIP_RETURN_CODES (*UnZip)(ZipContentInfo *const pZipInfo); +}; \ No newline at end of file diff --git a/CoDeLib/include/CoDeLib/IZip.h b/CoDeLib/include/CoDeLib/IZip.h new file mode 100644 index 00000000..94a13342 --- /dev/null +++ b/CoDeLib/include/CoDeLib/IZip.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +typedef enum { ZIP_SUCCESS, ZIP_ERROR } ZIP_RETURN_CODES; + +struct IZip { + /*! + * @brief Zips the input file(s) and write the output to the output file. + * @param pZipInfo The information about the zip file. The caller is + * responsible for cleaning up the provided pZipInfo pointer. + * @return ZIP_SUCCESS if the zipping was successful, ZIP_ERROR + * otherwise. + */ + ZIP_RETURN_CODES (*Zip)(const ZipContentInfo *const pZipInfo); +}; \ No newline at end of file diff --git a/CoDeLib/include/CoDeLib/UnZip_minizip/UnZip_minizip.h b/CoDeLib/include/CoDeLib/UnZip_minizip/UnZip_minizip.h new file mode 100644 index 00000000..e990f4b4 --- /dev/null +++ b/CoDeLib/include/CoDeLib/UnZip_minizip/UnZip_minizip.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern const struct IUnZip unzip_minizip; \ No newline at end of file diff --git a/CoDeLib/include/CoDeLib/ZipContentInfo/ZipContentInfo.h b/CoDeLib/include/CoDeLib/ZipContentInfo/ZipContentInfo.h new file mode 100644 index 00000000..306c39dd --- /dev/null +++ b/CoDeLib/include/CoDeLib/ZipContentInfo/ZipContentInfo.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +/*! +Usage example: + + ZipContentInfo zipInfo __attribute__((cleanup(ZipContentInfoClean))); + zipInfo = (ZipContentInfo){ + .name = RaiiStringCreateFromCString("myZip.zip"), + .pFileArray = NULL, + .fileCount = 0 + }; +*/ + +typedef struct { + // The name of the zip file. + RaiiString name; + + // The pointer to an array with al the files names in the zip file. + // The names are stored with any (sub)directories in the name. + // + // When unzipping the zip file, the files array is created and filled by the + // unzipping function. + RaiiString *pFileArray; + + // The number of files in the zip file. + // + // When unzipping the zip file, the fileCount is set by the unzipping + // function. + size_t fileCount; +} ZipContentInfo; + +void ZipContentInfoClean(ZipContentInfo *pZipInfo); \ No newline at end of file diff --git a/CoDeLib/include/CoDeLib/Zip_minizip/Zip_minizip.h b/CoDeLib/include/CoDeLib/Zip_minizip/Zip_minizip.h new file mode 100644 index 00000000..bbd30a1d --- /dev/null +++ b/CoDeLib/include/CoDeLib/Zip_minizip/Zip_minizip.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern const struct IZip zip_minizip; \ No newline at end of file diff --git a/Scripts/BuildAndInstallCoDeLib.py b/Scripts/BuildAndInstallCoDeLib.py index 23af455c..c7551998 100644 --- a/Scripts/BuildAndInstallCoDeLib.py +++ b/Scripts/BuildAndInstallCoDeLib.py @@ -49,6 +49,9 @@ def BuildAndInstallCoDeLib( ExternalZlibLibInstallPath = Path( ExternalLibPath / "zlib/Install" / targetPlatformString / BuildTypeString ) + ExternalMinizipNgLibInstallPath = Path( + ExternalLibPath / "minizip-ng/Install" / targetPlatformString / BuildTypeString + ) CoDeLibRootPath = Path(RepositoryRootPath / ProjectName) BuildDirectory = Path( @@ -70,14 +73,15 @@ def BuildAndInstallCoDeLib( print("==============================") print(ProjectName + ": Configuring ({})".format(BuildTypeString)) print("==============================") - configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S "{2}" -B "{3}" -DCMAKE_INSTALL_PREFIX="{4}" -DZLIB_ROOT="{5}" -DCMAKE_BUILD_TYPE={6}'.format( + configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S "{2}" -B "{3}" -DCMAKE_INSTALL_PREFIX="{4}" -DCMAKE_BUILD_TYPE={5} -DZLIB_ROOT="{6}" -DCMAKE_PREFIX_PATH="{7}"'.format( buildEnv.GetCmakeGenerator(), buildEnv.GetCustomToolChainPath(), CoDeLibRootPath, BuildDirectory, InstallDirectory, - ExternalZlibLibInstallPath, BuildTypeString, + ExternalZlibLibInstallPath, + ExternalMinizipNgLibInstallPath, ) print(configureCommand) subprocess.run( diff --git a/Scripts/BuildAndInstallExternalLibs.py b/Scripts/BuildAndInstallExternalLibs.py index b2a5cb27..916ca13d 100644 --- a/Scripts/BuildAndInstallExternalLibs.py +++ b/Scripts/BuildAndInstallExternalLibs.py @@ -112,8 +112,92 @@ def BuildAndInstallZlib( ) +############################## +# minizip-ng +############################## +def BuildAndInstallMinizipNg( + buildEnv: EnvironmentConfig.EnvironmentConfiguration, + buildConfig: EnvironmentConfig.BuildConfig = EnvironmentConfig.BuildConfig.DEBUG, +): + ProjectName = "minizip-ng" + + BuildTypeString = EnvironmentConfig.BuildConfig.ToCMakeBuildType(buildConfig) + targetPlatformString = EnvironmentConfig.Platform.PlatformToOsName( + buildEnv.GetTargetPlatform() + ) + + TopLevelCMakeListsDirectory = Path(ExternalLibPath / ProjectName) + BuildDirectory = Path( + ExternalLibPath / ProjectName / "Build" / targetPlatformString / BuildTypeString + ) + InstallDirectory = Path( + ExternalLibPath + / ProjectName + / "Install" + / targetPlatformString + / BuildTypeString + ) + + if not BuildDirectory.exists(): + BuildDirectory.mkdir(parents=True) + + if InstallDirectory.exists(): + shutil.rmtree(InstallDirectory) + InstallDirectory.mkdir(parents=True) + + os.chdir(RepositoryRootPath) + + # All options for minizip-ng that are not needed are turned off (all off them) except for MZ_COMPAT + # In this project minizing-ng is used only for zip file creation and extraction + print("==============================") + print(ProjectName + ": Configuring ({})".format(BuildTypeString)) + print("==============================") + configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S {2} -B {3} -DCMAKE_INSTALL_PREFIX="{4}" -DCMAKE_BUILD_TYPE={5} -DBUILD_SHARED_LIBS=OFF -DMZ_COMPAT=ON -DMZ_ZLIB=OFF -DMZ_BZIP2=OFF -DMZ_LZMA=OFF -DMZ_ZSTD=OFF -DMZ_LIBCOMP=OFF -DMZ_FETCH_LIBS=OFF -DMZ_PKCRYPT=OFF -DMZ_WZAES=OFF -DMZ_OPENSSL=OFF -DMZ_LIBBSD=OFF -DMZ_ICONV=OFF'.format( + buildEnv.GetCmakeGenerator(), + buildEnv.GetCustomToolChainPath(), + TopLevelCMakeListsDirectory, + BuildDirectory, + InstallDirectory, + BuildTypeString, + ) + print(configureCommand) + subprocess.run( + configureCommand, + shell=True, + check=True, + ) + + print("==============================") + print(ProjectName + ": Building ({})".format(BuildTypeString)) + print("==============================") + buildCommand = "cmake --build {0}".format(BuildDirectory) + print(buildCommand) + subprocess.run( + buildCommand, + shell=True, + check=True, + ) + + print("==============================") + print(ProjectName + ": Installing ({})".format(BuildTypeString)) + print("==============================") + installCommand = "cmake --install {0}".format(BuildDirectory) + print(installCommand) + subprocess.run( + installCommand, + shell=True, + check=True, + ) + + BuildEnv = EnvironmentConfig.EnvironmentConfiguration( RepositoryRootPath, targetPlatform ) + +# zlib BuildAndInstallZlib(BuildEnv, EnvironmentConfig.BuildConfig.DEBUG) BuildAndInstallZlib(BuildEnv, EnvironmentConfig.BuildConfig.RELEASE) + +# minizip-ng +BuildAndInstallMinizipNg(BuildEnv, EnvironmentConfig.BuildConfig.DEBUG) +BuildAndInstallMinizipNg(BuildEnv, EnvironmentConfig.BuildConfig.RELEASE) diff --git a/Scripts/BuildBenchmark.py b/Scripts/BuildBenchmark.py index 3e97c360..df44e152 100644 --- a/Scripts/BuildBenchmark.py +++ b/Scripts/BuildBenchmark.py @@ -55,6 +55,9 @@ def BuildBenchmark( ExternalZlibLibInstallPath = Path( ExternalLibPath / "zlib/Install" / targetPlatformString / BuildTypeString ) + ExternalMinizipNgLibInstallPath = Path( + ExternalLibPath / "minizip-ng/Install" / targetPlatformString / BuildTypeString + ) BenchmarkRootPath = Path(RepositoryRootPath / ProjectName) BuildDirectory = Path( @@ -69,14 +72,15 @@ def BuildBenchmark( print("==============================") print(ProjectName + ": Configuring ({})".format(BuildTypeString)) print("==============================") - configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -DCMAKE_PREFIX_PATH="{2}" -S {3} -B {4} -DZLIB_ROOT="{5}" -DCMAKE_BUILD_TYPE={6}'.format( + configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S {2} -B {3} -DCMAKE_BUILD_TYPE={4} -DZLIB_ROOT="{5}" -DCMAKE_PREFIX_PATH="{6};{7}"'.format( buildEnv.GetCmakeGenerator(), buildEnv.GetCustomToolChainPath(), - CoDeLibInstallDirectory, BenchmarkRootPath, BuildDirectory, - ExternalZlibLibInstallPath, BuildTypeString, + ExternalZlibLibInstallPath, + CoDeLibInstallDirectory, + ExternalMinizipNgLibInstallPath, ) subprocess.run( configureCommand, diff --git a/Scripts/CleanAll.py b/Scripts/CleanAll.py index ada4126e..7866e48d 100644 --- a/Scripts/CleanAll.py +++ b/Scripts/CleanAll.py @@ -16,6 +16,8 @@ ExternalLibPath = Path(ProjectRootPath / "External") ExternalZlibLibBuildPath = Path(ExternalLibPath / "zlib/Build") ExternalZlibLibInstallPath = Path(ExternalLibPath / "zlib/Install") +ExternalMinizipNgLibBuildPath = Path(ExternalLibPath / "minizip-ng/Build") +ExternalMinizipNgLibInstallPath = Path(ExternalLibPath / "minizip-ng/Install") DirectoriesToRemove = [ BenchmarkBuildPath, @@ -23,6 +25,8 @@ CoDeLibInstallPath, ExternalZlibLibBuildPath, ExternalZlibLibInstallPath, + ExternalMinizipNgLibBuildPath, + ExternalMinizipNgLibInstallPath, ]