bit7z

repository·master·Indexed 21 days ago

https://github.com/rikyoz/bit7z

A cross-platform C++ static library providing a high-level wrapper interface for 7-Zip shared libraries (DLLs/SOs). It supports compression and extraction for formats including 7z, XZ, BZIP2, GZIP, TAR, ZIP, and WIM, as well as reading metadata and stream-based processing. Compatible with Windows, Linux, macOS, and BSD using C++14 or later.

Tokens
4.2K
Snippets
9
Records
12
Agent score
25%

What's inside bit7z

  1. Overview of bit7z features and capabilities

    master

    bit7z is a cross-platform C++ static library that provides a clean wrapper interface for 7-Zip shared libraries. It enables compression, extraction, and archive manipulation.

    Core Capabilities

    • Compression Formats: 7z, XZ, BZIP2, GZIP, TAR, ZIP, and WIM.
    • Extraction Formats: Extensive support including 7z, RAR, RAR5, ZIP, ISO, DMG, DEB, RPM, and many others.
    • Archive Manipulation: Reading metadata, testing archives for errors, updating existing archives, and renaming/deleting items.
    • Advanced Data Handling: Compression/extraction to/from memory and C++ standard streams; reading nested/sub-archives without intermediate files.
    • Security: AES-256 encryption for 7z and ZIP; header encryption for 7z.
    • Control: Operation progress callbacks, pausing/canceling operations, and automatic format detection.

    Important Constraints

    • DLL Dependency: Feature availability depends on the specific 7-Zip shared library used (e.g., 7z.dll supports all features, while 7za.dll is limited to the 7z format).
    • Compilation Requirements: Certain features like automatic format detection and selective extraction using regular expressions are disabled by default and require specific macro definitions during compilation.
  2. Handle string encoding and Unicode

    master

    bit7z follows the UTF-8 Everywhere Manifesto by default: std::string is used for paths, and all input/output strings are assumed to be UTF-8 encoded.

    Windows Considerations

    On Windows, std::string often uses the system code page (e.g., Windows-1252) instead of UTF-8. To handle non-ASCII characters, choose one of these strategies:

    1. Recommended (Windows 10 1903+): Enforce the UTF-8 code page for your entire application.

    2. Manual UTF-8 Management:

      • Use C++11 UTF-8 literals for input.
      • Convert user input (like passwords) from UTF-16 wide strings to UTF-8 using bit7z::to_tstring.
      • Call SetConsoleOutputCP(CP_UTF8) to correctly print UTF-8 output to the console.
    3. Use Native Wide Strings (Windows-only focus): Enable BIT7Z_USE_NATIVE_STRING via CMake to use std::wstring. This avoids internal conversions but makes cross-platform development more complex. Use the bit7z::tstring type alias and BIT7Z_STRING macro for portability.

      If using this mode, you must set the console mode to UTF-16:

      _setmode(_fileno(stdout), _O_U16TEXT);
      _setmode(_fileno(stdin), _O_U16TEXT);
    4. System Code Page (Not Recommended): Enable BIT7Z_USE_SYSTEM_CODEPAGE via CMake. This limits the character set available to your application.

    #include <fcntl.h> //for _O_U16TEXT
    #include <io.h>  //for _setmode
    
    _setmode(_fileno(stdout), _O_U16TEXT); // setting the stdout encoding to UTF16
    _setmode(_fileno(stdin), _O_U16TEXT); // setting the stdin encoding to UTF16
  3. Install bit7z via CPM.cmake

    master

    Use CPMAddPackage to fetch and integrate bit7z automatically. Replace <version> with your desired version.

    CPMAddPackage("gh:rikyoz/bit7z@<version>")
    target_link_libraries(${YOUR_TARGET} PRIVATE bit7z)
    CPMAddPackage("gh:rikyoz/bit7z@<version>")
    # Optional: set(BIT7Z_AUTO_FORMAT ON CACHE BOOL "enable auto format support" FORCE)
    target_link_libraries(${YOUR_TARGET} PRIVATE bit7z)
  4. Ensure compatibility with legacy 7-Zip or p7zip

    master

    By default, bit7z is compatible with 7-Zip v23.01 and later. On Linux and macOS, 7-Zip v23.01 introduced breaking changes to the IUnknown interface, making it incompatible with older versions (v22.01 and earlier) or p7zip.

    To use older shared libraries (7z.so from p7zip or 7-Zip v22.01 and earlier), use one of the following methods:

    1. Configure bit7z with -DBIT7Z_USE_LEGACY_IUNKNOWN=ON.
    2. Configure bit7z specifically for version 22.01 using -DBIT7Z_7ZIP_VERSION="22.01".

    Note: If you are building 7-Zip v23.01 in backward-compatible mode using the Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN macro, you must still enable BIT7Z_USE_LEGACY_IUNKNOWN in bit7z to maintain compatibility with previous versions.

    cmake .. -DBIT7Z_USE_LEGACY_IUNKNOWN=ON
  5. Install bit7z via vcpkg

    master
    1. Install the package using vcpkg:

      vcpkg install bit7z
    2. Add it to your CMakeLists.txt:

      find_package(bit7z CONFIG REQUIRED)
      target_link_libraries(${YOUR_TARGET} PRIVATE bit7z::bit7z)
    vcpkg install bit7z
    find_package(bit7z CONFIG REQUIRED)
    target_link_libraries(${YOUR_TARGET} PRIVATE bit7z::bit7z)
  6. Migrating from bit7z v3 to v4

    master

    Version 4 introduces several breaking changes:

    • String Encoding: The library now follows the UTF-8 Everywhere Manifesto. The default string type is std::string (UTF-8) instead of std::wstring. To restore Windows-native behavior, use the CMake option -DBIT7Z_USE_NATIVE_STRING.
    • Renamed Classes:
      • BitExtractor $\rightarrow$ BitFileExtractor (Note: BitExtractor is now a template class).
      • BitCompressor $\rightarrow$ BitFileCompressor (Note: BitCompressor is now a template class).
      • BitArchiveInfo $\rightarrow$ BitArchiveReader.
    • Exception Changes: BitException now inherits from std::system_error. getErrorCode() is renamed to hresultCode().
    • Callback Changes: ProgressCallback must now return a bool (true to continue, false to stop).
    • Header Paths: Headers moved to include/bit7z/. You must use #include <bit7z/header_name.hpp>.
    • Dependency Management: Third-party dependencies are now handled via CPM.cmake instead of git submodules.
  7. Read archive metadata using BitArchiveReader

    master

    Use BitArchiveReader to inspect the contents and properties of an existing archive without extracting it.

    Archive Properties:

    • itemsCount(): Total number of items.
    • foldersCount(): Number of folders.
    • filesCount(): Number of files.
    • size(): Total uncompressed size.
    • packSize(): Total compressed size.

    Individual Item Metadata (iterating over the BitArchiveReader object):

    • index(): Item index.
    • name(): File/folder name.
    • extension(): File extension.
    • path(): Relative path.
    • isDir(): Boolean indicating if it is a directory.
    • size(): Uncompressed size of the item.
    • packSize(): Compressed size of the item.
    • crc(): CRC value (hexadecimal).
    #include <bit7z/bitarchivereader.hpp>
    
    try {
        using namespace bit7z;
    
        Bit7zLibrary lib{ "7za.dll" };
        BitArchiveReader arc{ lib, "archive.7z", BitFormat::SevenZip };
    
        // Printing archive metadata
        std::cout << "Archive properties\n";
        std::cout << "  Items count: "   << arc.itemsCount() << '\n';
        std::cout << "  Folders count: "   << arc.foldersCount() << '\n';
        std::cout << "  Files count: "     << arc.filesCount() << '\n';
        std::cout << "  Size: "           << arc.size() <<'\n';
        std::cout << "  Packed size: "    << arc.packSize() << "\n\n";
    
        // Printing the metadata of the archived items
        std::cout << "Archived items";
        for ( const auto& item : arc ) {
            std::cout << '\n';
            std::cout << "  Item index: "    << item.index() << '\n';
            std::cout << "    Name: "        << item.name() << '\n';
            std::cout << "    Extension: "   << item.extension() << '\n';
            std::cout << "    Path: "        << item.path() << '\n';
            std::cout << "    IsDir: "       << item.isDir() << '\n';
            std::cout << "    Size: "        << item.size() << '\n';
            std::cout << "    Packed size: " << item.packSize() << '\n';
            std::cout << "    CRC: " << std::hex << item.crc() << std::dec << '\n';
        }
        std::cout.flush();
    } catch ( const bit7z::BitException& ex ) { /* Handle error */ }
  8. Extract files from an archive using BitFileExtractor

    master

    Use BitFileExtractor to extract files from an archive. You must first initialize a Bit7zLibrary with the path to a 7-Zip shared library (e.g., 7za.dll or 7z.so).

    Common tasks include:

    • Extracting an entire archive to a directory.
    • Extracting a specific file by name using extractMatching.
    • Extracting a file directly into a memory buffer (std::vector<byte_t>).
    • Handling encrypted archives by calling setPassword before extraction.

    All bit7z operations should be wrapped in a try-catch block to handle bit7z::BitException errors.

    #include <bit7z/bitfileextractor.hpp>
    
    try {
        using namespace bit7z;
    
        Bit7zLibrary lib{ "7za.dll" };
        BitFileExtractor extractor{ lib, BitFormat::SevenZip };
    
        // Extracting a simple archive
        extractor.extract( "path/to/archive.7z", "out/dir/" );
    
        // Extracting a specific file inside an archive
        extractor.extractMatching( "path/to/archive.7z", "file.pdf", "out/dir/" );
    
        // Extracting the first file of an archive to a buffer
        std::vector< byte_t > buffer;
        extractor.extract( "path/to/archive.7z", buffer );
    
        // Extracting an encrypted archive
        extractor.setPassword( "password" );
        extractor.extract( "path/to/another/archive.7z", "out/dir/" );
    } catch ( const bit7z::BitException& ex ) { /* Handle error */ }
  9. Configure the 7-Zip version via CMake

    master

    bit7z automatically downloads the latest supported 7-Zip version during configuration. However, you can manually specify a version or a custom source path using CMake options.

    It is highly recommended to use the same version of 7-Zip shared libraries at runtime that you used during the build process.

    CMake Options:

    • BIT7Z_7ZIP_VERSION: Specify a version string (e.g., -DBIT7Z_7ZIP_VERSION="22.01").
    • BIT7Z_CUSTOM_7ZIP_PATH: Specify a custom path containing the 7-Zip source code.
    cmake .. -DBIT7Z_7ZIP_VERSION="22.01"
  10. bit7z platform and compiler requirements

    master

    bit7z is designed for cross-platform compatibility with the following requirements:

    Supported Platforms & Architectures

    • Operating Systems: Windows, Linux, macOS, and BSD.
    • Architectures: x86, x64, arm, and arm64.

    Supported Compilers

    • Windows: MSVC 2015 or later.
    • Unix/Linux/macOS:
      • GCC 4.9 or later
      • Clang 3.6 or later
      • MinGW 6.4+

    Language Standard

    • Requires C++14 or later.
  11. Compress files into an archive using BitFileCompressor

    master

    Use BitFileCompressor to create new archives. You must provide a Bit7zLibrary instance and specify the target BitFormat (e.g., BitFormat::Zip).

    Supported operations:

    • Simple compression: Pass a std::vector<std::string> of file paths.
    • Custom directory structure: Pass a std::map<std::string, std::string> where the key is the source path and the value is the desired alias/path inside the archive.
    • Directory compression: Use compressDirectory to archive an entire folder.
    • Encrypted archives: Call setPassword before calling compressFiles.
    • Update mode: Use setUpdateMode(UpdateMode::Append) to add files to an existing archive.
    • Buffer compression: Use compressFile to compress a single file directly into a std::vector<bit7z::byte_t> buffer.

    Alternatively, use BitArchiveWriter to add files/directories to an archive object before calling compressTo to finalize the output.

    #include <bit7z/bitfilecompressor.hpp>
    
    try {
        using namespace bit7z;
    
        Bit7zLibrary lib{ "7z.dll" };
        BitFileCompressor compressor{ lib, BitFormat::Zip };
    
        std::vector< std::string > files = { "path/to/file1.jpg", "path/to/file2.pdf" };
    
        // Creating a simple zip archive
        compressor.compress( files, "output_archive.zip" );
    
        // Creating a zip archive with a custom directory structure
        std::map< std::string, std::string > files_map = {
            { "path/to/file1.jpg", "alias/path/file1.jpg" },
            { "path/to/file2.pdf", "alias/path/file2.pdf" }
        };
        compressor.compress( files_map, "output_archive2.zip" );
    
        // Compressing a directory
        compressor.compressDirectory( "dir/path/", "dir_archive.zip" );
    
        // Creating an encrypted zip archive of two files
        compressor.setPassword( "password" );
        compressor.compressFiles( files, "protected_archive.zip" );
    
        // Updating an existing zip archive
        compressor.setUpdateMode( UpdateMode::Append );
        compressor.compressFiles( files, "existing_archive.zip" );
    
        // Compressing a single file into a buffer
        std::vector< bit7z::byte_t > buffer;
        BitFileCompressor compressor2{ lib, BitFormat::BZip2 };
        compressor2.compressFile( files[0], buffer );
    } catch ( const bit7z::BitException& ex ) { /* Handle error */ }
  12. Install bit7z via CMake add_subdirectory

    master

    To integrate bit7z directly into your CMake project:

    1. Download the bit7z source to a subdirectory (e.g., third_party).
    2. Add add_subdirectory() to your CMakeLists.txt.
    3. Link the library using target_link_libraries().

    You can control build options like BIT7Z_USE_NATIVE_STRING before linking.

    add_subdirectory(${CMAKE_SOURCE_DIR}/third_party/bit7z)
    # Optional: set(BIT7Z_USE_NATIVE_STRING ON CACHE BOOL "enable using native OS strings" FORCE)
    target_link_libraries(${YOUR_TARGET} PRIVATE bit7z)