Ticket #13742: 0001-Package-Kit-add-Zstd-compression.patch

File 0001-Package-Kit-add-Zstd-compression.patch, 27.1 KB (added by korli, 7 years ago)

Draft patch to add Zstd as Hpkg compression format

  • Jamfile

    From 91ee6c66d7be5c343475d8a387ad0e189065f119 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= <jerome.duval@gmail.com>
    Date: Tue, 17 Oct 2017 22:22:03 +0200
    Subject: [PATCH] Package Kit: add Zstd compression.
    
    * build zstd as static kernel lib when available.
    * packagefs includes zstd support when available.
    ---
     Jamfile                                            |   2 +-
     build/jam/BuildFeatures                            |  23 ++
     .../private/support/ZstdCompressionAlgorithm.h     |   1 +
     headers/os/package/hpkg/HPKGDefs.h                 |   3 +-
     headers/private/support/ZstdCompressionAlgorithm.h |  97 +++++
     src/add-ons/kernel/file_systems/packagefs/Jamfile  |  15 +-
     src/bin/package/command_create.cpp                 |  14 +-
     src/bin/package/command_recompress.cpp             |  14 +-
     src/bin/package/package.cpp                        |   2 +
     src/kits/Jamfile                                   |   1 +
     src/kits/package/Jamfile                           |   4 +-
     src/kits/package/hpkg/ReaderImplBase.cpp           |  14 +
     src/kits/package/hpkg/WriterImplBase.cpp           |  24 ++
     src/kits/support/Jamfile                           |  10 +
     src/kits/support/ZstdCompressionAlgorithm.cpp      | 405 +++++++++++++++++++++
     src/system/kernel/lib/Jamfile                      |   3 +
     src/system/kernel/lib/zstd/Jamfile                 |  26 ++
     17 files changed, 644 insertions(+), 14 deletions(-)
     create mode 100644 headers/build/private/support/ZstdCompressionAlgorithm.h
     create mode 100644 headers/private/support/ZstdCompressionAlgorithm.h
     create mode 100644 src/kits/support/ZstdCompressionAlgorithm.cpp
     create mode 100644 src/system/kernel/lib/zstd/Jamfile
    
    diff --git a/Jamfile b/Jamfile
    index b9acc0e..e4ab659 100644
    a b for architectureObject in [ MultiArchSubDirSetup ] {  
    2323# Include required packages:
    2424# primary architecture
    2525AddHaikuImagePackages [ FFilterByBuildFeatures
    26     bash bc coreutils curl freetype icu libsolv zlib
     26    bash bc coreutils curl freetype icu libsolv zlib zstd
    2727
    2828    regular_image @{
    2929        bzip2 ctags diffutils expat ffmpeg findutils gawk glu grep gutenprint
  • build/jam/BuildFeatures

    diff --git a/build/jam/BuildFeatures b/build/jam/BuildFeatures
    index fec1521..28498c1 100644
    a b if $(TARGET_PACKAGING_ARCH) = x86_64 {  
    677677    }
    678678}
    679679
     680
     681# zstd
     682if [ IsPackageAvailable zstd_devel ] {
     683    ExtractBuildFeatureArchives zstd :
     684        file: base zstd
     685            runtime: lib
     686        file: devel zstd_devel
     687            depends: base
     688            library: $(developLibDir)/libzstd.so
     689            headers: $(developHeadersDir)
     690        # sources are required for the primary architecture only
     691        primary @{
     692            file: source zstd_source
     693                sources: develop/sources/%portRevisionedName%/sources
     694        }@
     695        ;
     696
     697    EnableBuildFeatures zstd ;
     698} else {
     699    Echo "zstd support not available on $(TARGET_PACKAGING_ARCH)" ;
     700}
     701
     702
    680703# ATA Drivers + Bus
    681704EnableBuildFeatures ata ;
  • new file headers/build/private/support/ZstdCompressionAlgorithm.h

    diff --git a/headers/build/private/support/ZstdCompressionAlgorithm.h b/headers/build/private/support/ZstdCompressionAlgorithm.h
    new file mode 100644
    index 0000000..a2f0a7c
    - +  
     1#include <../private/support/ZstdCompressionAlgorithm.h>
  • headers/os/package/hpkg/HPKGDefs.h

    diff --git a/headers/os/package/hpkg/HPKGDefs.h b/headers/os/package/hpkg/HPKGDefs.h
    index 4650a7f..ba7735c 100644
    a b enum BHPKGAttributeID {  
    9898// compression types
    9999enum {
    100100    B_HPKG_COMPRESSION_NONE = 0,
    101     B_HPKG_COMPRESSION_ZLIB = 1
     101    B_HPKG_COMPRESSION_ZLIB = 1,
     102    B_HPKG_COMPRESSION_ZSTD = 2
    102103};
    103104
    104105
  • new file headers/private/support/ZstdCompressionAlgorithm.h

    diff --git a/headers/private/support/ZstdCompressionAlgorithm.h b/headers/private/support/ZstdCompressionAlgorithm.h
    new file mode 100644
    index 0000000..df75e16
    - +  
     1/*
     2 * Copyright 2017, Jérôme Duval.
     3 * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
     4 * Distributed under the terms of the MIT License.
     5 */
     6#ifndef _ZSTD_COMPRESSION_ALGORITHM_H_
     7#define _ZSTD_COMPRESSION_ALGORITHM_H_
     8
     9
     10#include <CompressionAlgorithm.h>
     11
     12
     13// compression level
     14enum {
     15    B_ZSTD_COMPRESSION_NONE     = 0,
     16    B_ZSTD_COMPRESSION_FASTEST  = 1,
     17    B_ZSTD_COMPRESSION_BEST     = 19,
     18    B_ZSTD_COMPRESSION_DEFAULT  = 2,
     19};
     20
     21
     22class BZstdCompressionParameters : public BCompressionParameters {
     23public:
     24                                BZstdCompressionParameters(
     25                                    int compressionLevel
     26                                        = B_ZSTD_COMPRESSION_DEFAULT);
     27    virtual                     ~BZstdCompressionParameters();
     28
     29            int32               CompressionLevel() const;
     30            void                SetCompressionLevel(int32 level);
     31
     32            size_t              BufferSize() const;
     33            void                SetBufferSize(size_t size);
     34
     35private:
     36            int32               fCompressionLevel;
     37            size_t              fBufferSize;
     38};
     39
     40
     41class BZstdDecompressionParameters : public BDecompressionParameters {
     42public:
     43                                BZstdDecompressionParameters();
     44    virtual                     ~BZstdDecompressionParameters();
     45
     46            size_t              BufferSize() const;
     47            void                SetBufferSize(size_t size);
     48
     49private:
     50            size_t              fBufferSize;
     51};
     52
     53
     54class BZstdCompressionAlgorithm : public BCompressionAlgorithm {
     55public:
     56                                BZstdCompressionAlgorithm();
     57    virtual                     ~BZstdCompressionAlgorithm();
     58
     59    virtual status_t            CreateCompressingInputStream(BDataIO* input,
     60                                    const BCompressionParameters* parameters,
     61                                    BDataIO*& _stream);
     62    virtual status_t            CreateCompressingOutputStream(BDataIO* output,
     63                                    const BCompressionParameters* parameters,
     64                                    BDataIO*& _stream);
     65    virtual status_t            CreateDecompressingInputStream(BDataIO* input,
     66                                    const BDecompressionParameters* parameters,
     67                                    BDataIO*& _stream);
     68    virtual status_t            CreateDecompressingOutputStream(BDataIO* output,
     69                                    const BDecompressionParameters* parameters,
     70                                    BDataIO*& _stream);
     71
     72    virtual status_t            CompressBuffer(const void* input,
     73                                    size_t inputSize, void* output,
     74                                    size_t outputSize, size_t& _compressedSize,
     75                                    const BCompressionParameters* parameters
     76                                        = NULL);
     77    virtual status_t            DecompressBuffer(const void* input,
     78                                    size_t inputSize, void* output,
     79                                    size_t outputSize,
     80                                    size_t& _uncompressedSize,
     81                                    const BDecompressionParameters* parameters
     82                                        = NULL);
     83
     84private:
     85            struct CompressionStrategy;
     86            struct DecompressionStrategy;
     87
     88            template<typename BaseClass, typename Strategy, typename StreamType> struct Stream;
     89            template<typename BaseClass, typename Strategy, typename StreamType>
     90                friend struct Stream;
     91
     92private:
     93    static  status_t            _TranslateZstdError(size_t error);
     94};
     95
     96
     97#endif  // _ZSTD_COMPRESSION_ALGORITHM_H_
  • src/add-ons/kernel/file_systems/packagefs/Jamfile

    diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile
    index 52aebe0..7852d82 100644
    a b UseBuildFeatureHeaders zlib ;  
    55UsePrivateKernelHeaders ;
    66UsePrivateHeaders package shared storage support ;
    77
     8local zstdSources ;
     9local zstdKernelLib ;
     10
     11if [ FIsBuildFeatureEnabled zstd ] {
     12    zstdSources = ZstdCompressionAlgorithm.cpp ;
     13    zstdKernelLib = kernel_libzstd.a ;
     14    UseBuildFeatureHeaders zstd ;
     15    Includes [ FGristFiles $(zstdSources) ]
     16        : [ BuildFeatureAttribute zstd : headers ] ;
     17    SubDirC++Flags -DZSTD_ENABLED ;
     18}
     19
    820
    921local subDirs =
    1022    indices
    local storageKitSources =  
    117129local supportKitSources =
    118130    CompressionAlgorithm.cpp
    119131    ZlibCompressionAlgorithm.cpp
     132    $(zstdSources)
    120133;
    121134
    122135KernelAddon packagefs
    KernelAddon packagefs  
    129142    $(storageKitSources)
    130143    $(supportKitSources)
    131144
    132     : kernel_libz.a
     145    : kernel_libz.a $(zstdKernelLib)
    133146;
    134147
    135148
  • src/bin/package/command_create.cpp

    diff --git a/src/bin/package/command_create.cpp b/src/bin/package/command_create.cpp
    index ed24982..3989f20 100644
    a b command_create(int argc, const char* const* argv)  
    3939    bool quiet = false;
    4040    bool verbose = false;
    4141    int32 compressionLevel = BPackageKit::BHPKG::B_HPKG_COMPRESSION_LEVEL_BEST;
     42    int32 compression = BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZLIB;
    4243
    4344    while (true) {
    4445        static struct option sLongOptions[] = {
    command_create(int argc, const char* const* argv)  
    4950        };
    5051
    5152        opterr = 0; // don't print errors
    52         int c = getopt_long(argc, (char**)argv, "+b0123456789C:hi:I:qv",
     53        int c = getopt_long(argc, (char**)argv, "+b0123456789C:hi:I:qvz",
    5354            sLongOptions, NULL);
    5455        if (c == -1)
    5556            break;
    command_create(int argc, const char* const* argv)  
    9697                verbose = true;
    9798                break;
    9899
     100            case 'z':
     101                compression = BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZSTD;
     102                break;
     103
    99104            default:
    100105                print_usage_and_exit(true);
    101106                break;
    command_create(int argc, const char* const* argv)  
    118123    // create package
    119124    BPackageWriterParameters writerParameters;
    120125    writerParameters.SetCompressionLevel(compressionLevel);
    121     if (compressionLevel == 0) {
    122         writerParameters.SetCompression(
    123             BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE);
    124     }
     126    if (compressionLevel == 0)
     127        compression = BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE;
     128    writerParameters.SetCompression(compression);
    125129
    126130    PackageWriterListener listener(verbose, quiet);
    127131    BPackageWriter packageWriter(&listener);
  • src/bin/package/command_recompress.cpp

    diff --git a/src/bin/package/command_recompress.cpp b/src/bin/package/command_recompress.cpp
    index c380a3e..8529c4d 100644
    a b command_recompress(int argc, const char* const* argv)  
    4545    bool quiet = false;
    4646    bool verbose = false;
    4747    int32 compressionLevel = BPackageKit::BHPKG::B_HPKG_COMPRESSION_LEVEL_BEST;
     48    int32 compression = BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZLIB;
    4849
    4950    while (true) {
    5051        static struct option sLongOptions[] = {
    command_recompress(int argc, const char* const* argv)  
    5556        };
    5657
    5758        opterr = 0; // don't print errors
    58         int c = getopt_long(argc, (char**)argv, "+0123456789:hqv",
     59        int c = getopt_long(argc, (char**)argv, "+0123456789:hqvz",
    5960            sLongOptions, NULL);
    6061        if (c == -1)
    6162            break;
    command_recompress(int argc, const char* const* argv)  
    8687                verbose = true;
    8788                break;
    8889
     90            case 'z':
     91                compression = BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZSTD;
     92                break;
     93
    8994            default:
    9095                print_usage_and_exit(true);
    9196                break;
    command_recompress(int argc, const char* const* argv)  
    119124    // write the output package
    120125    BPackageWriterParameters writerParameters;
    121126    writerParameters.SetCompressionLevel(compressionLevel);
    122     if (compressionLevel == 0) {
    123         writerParameters.SetCompression(
    124             BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE);
    125     }
     127    if (compressionLevel == 0)
     128        compression = BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE;
     129    writerParameters.SetCompression(compression);
    126130
    127131    PackageWriterListener listener(verbose, quiet);
    128132    BPackageWriter packageWriter(&listener);
  • src/bin/package/package.cpp

    diff --git a/src/bin/package/package.cpp b/src/bin/package/package.cpp
    index d47b8bc..88af5ca 100644
    a b static const char* kUsage =  
    7272    "                 to redirect a \"make install\". Only allowed with -b.\n"
    7373    "    -q         - Be quiet (don't show any output except for errors).\n"
    7474    "    -v         - Be verbose (show more info about created package).\n"
     75    "    -z         - Use Zstd compression.\n"
    7576    "\n"
    7677    "  dump [ <options> ] <package>\n"
    7778    "    Dumps the TOC section of package file <package>. For debugging only.\n"
    static const char* kUsage =  
    120121    "                 Defaults to 9.\n"
    121122    "    -q         - Be quiet (don't show any output except for errors).\n"
    122123    "    -v         - Be verbose (show more info about created package).\n"
     124    "    -z         - Use Zstd compression.\n"
    123125    "\n"
    124126    "Common Options:\n"
    125127    "  -h, --help   - Print this usage info.\n"
  • src/kits/Jamfile

    diff --git a/src/kits/Jamfile b/src/kits/Jamfile
    index ca14ca8..cd091b3 100644
    a b for architectureObject in [ MultiArchSubDirSetup ] {  
    4848            [ TargetLibstdc++ ]
    4949            [ BuildFeatureAttribute icu : libraries ]
    5050            [ BuildFeatureAttribute zlib : library ]
     51            [ BuildFeatureAttribute zstd : library ]
    5152            ;
    5253    }
    5354}
  • src/kits/package/Jamfile

    diff --git a/src/kits/package/Jamfile b/src/kits/package/Jamfile
    index b849ecf..98b03b9 100644
    a b local architectureObject ;  
    6262for architectureObject in [ MultiArchSubDirSetup ] {
    6363    on $(architectureObject) {
    6464        UseBuildFeatureHeaders curl ;
    65 
     65        if [ FIsBuildFeatureEnabled zstd ] {
     66            SubDirC++Flags -DZSTD_ENABLED ;
     67        }
    6668        SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ;
    6769        SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg v1 ] ;
    6870        SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package manager ] ;
  • src/kits/package/hpkg/ReaderImplBase.cpp

    diff --git a/src/kits/package/hpkg/ReaderImplBase.cpp b/src/kits/package/hpkg/ReaderImplBase.cpp
    index bb3bb1b..65414c0 100644
    a b  
    2020#include <DataIO.h>
    2121
    2222#include <ZlibCompressionAlgorithm.h>
     23#include <ZstdCompressionAlgorithm.h>
    2324
    2425#include <package/hpkg/HPKGDefsPrivate.h>
    2526#include <package/hpkg/PackageFileHeapReader.h>
    ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize,  
    824825                return B_NO_MEMORY;
    825826            }
    826827            break;
     828#ifdef ZSTD_ENABLED
     829        case B_HPKG_COMPRESSION_ZSTD:
     830            decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
     831                new(std::nothrow) BZstdCompressionAlgorithm,
     832                new(std::nothrow) BZstdDecompressionParameters);
     833            decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
     834            if (decompressionAlgorithm == NULL
     835                || decompressionAlgorithm->algorithm == NULL
     836                || decompressionAlgorithm->parameters == NULL) {
     837                return B_NO_MEMORY;
     838            }
     839            break;
     840#endif
    827841        default:
    828842            fErrorOutput->PrintError("Error: Invalid heap compression\n");
    829843            return B_BAD_DATA;
  • src/kits/package/hpkg/WriterImplBase.cpp

    diff --git a/src/kits/package/hpkg/WriterImplBase.cpp b/src/kits/package/hpkg/WriterImplBase.cpp
    index 7db79e1..1ca9156 100644
    a b  
    2020
    2121#include <AutoDeleter.h>
    2222#include <ZlibCompressionAlgorithm.h>
     23#include <ZstdCompressionAlgorithm.h>
    2324
    2425#include <package/hpkg/DataReader.h>
    2526#include <package/hpkg/ErrorOutput.h>
    WriterImplBase::InitHeapReader(size_t headerSize)  
    326327                throw std::bad_alloc();
    327328            }
    328329            break;
     330#ifdef ZSTD_ENABLED
     331        case B_HPKG_COMPRESSION_ZSTD:
     332            compressionAlgorithm = CompressionAlgorithmOwner::Create(
     333                new(std::nothrow) BZstdCompressionAlgorithm,
     334                new(std::nothrow) BZstdCompressionParameters(
     335                    fParameters.CompressionLevel()));
     336            compressionAlgorithmReference.SetTo(compressionAlgorithm, true);
     337
     338            decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
     339                new(std::nothrow) BZstdCompressionAlgorithm,
     340                new(std::nothrow) BZstdDecompressionParameters);
     341            decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
     342
     343            if (compressionAlgorithm == NULL
     344                || compressionAlgorithm->algorithm == NULL
     345                || compressionAlgorithm->parameters == NULL
     346                || decompressionAlgorithm == NULL
     347                || decompressionAlgorithm->algorithm == NULL
     348                || decompressionAlgorithm->parameters == NULL) {
     349                throw std::bad_alloc();
     350            }
     351            break;
     352#endif
    329353        default:
    330354            fErrorOutput->PrintError("Error: Invalid heap compression\n");
    331355            return B_BAD_VALUE;
  • src/kits/support/Jamfile

    diff --git a/src/kits/support/Jamfile b/src/kits/support/Jamfile
    index 397e86d..df359db 100644
    a b local architectureObject ;  
    88for architectureObject in [ MultiArchSubDirSetup ] {
    99    on $(architectureObject) {
    1010        local architecture = $(TARGET_PACKAGING_ARCH) ;
     11        local zstdSources ;
    1112
    1213        UseBuildFeatureHeaders zlib ;
    1314
    1415        Includes [ FGristFiles ZlibCompressionAlgorithm.cpp ]
    1516            : [ BuildFeatureAttribute zlib : headers ] ;
    1617
     18        if [ FIsBuildFeatureEnabled zstd ] {
     19            UseBuildFeatureHeaders zstd ;
     20            zstdSources = ZstdCompressionAlgorithm.cpp ;
     21
     22            Includes [ FGristFiles ZstdCompressionAlgorithm.cpp ]
     23                : [ BuildFeatureAttribute zstd : headers ] ;
     24        }
     25
    1726        # BUrl uses ICU to perform IDNA conversions (unicode domain names)
    1827        UseBuildFeatureHeaders icu ;
    1928        Includes [ FGristFiles Url.cpp ]
    for architectureObject in [ MultiArchSubDirSetup ] {  
    4655            Url.cpp
    4756            Uuid.cpp
    4857            ZlibCompressionAlgorithm.cpp
     58            $(zstdSources)
    4959            ;
    5060
    5161        StaticLibrary [ MultiArchDefaultGristFiles libreferenceable.a ]
  • new file src/kits/support/ZstdCompressionAlgorithm.cpp

    diff --git a/src/kits/support/ZstdCompressionAlgorithm.cpp b/src/kits/support/ZstdCompressionAlgorithm.cpp
    new file mode 100644
    index 0000000..d174eb5
    - +  
     1/*
     2 * Copyright 2017, Jérôme Duval.
     3 * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
     4 * Distributed under the terms of the MIT License.
     5 */
     6
     7
     8#include <ZstdCompressionAlgorithm.h>
     9
     10#include <errno.h>
     11#include <string.h>
     12
     13#include <algorithm>
     14#include <new>
     15
     16#include <zstd.h>
     17#include <zstd_errors.h>
     18
     19#include <DataIO.h>
     20
     21
     22// build compression support only for userland
     23#if !defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
     24#   define B_ZSTD_COMPRESSION_SUPPORT 1
     25#endif
     26
     27
     28static const size_t kMinBufferSize      = 1024;
     29static const size_t kMaxBufferSize      = 1024 * 1024;
     30static const size_t kDefaultBufferSize  = 4 * 1024;
     31
     32
     33static size_t
     34sanitize_buffer_size(size_t size)
     35{
     36    if (size < kMinBufferSize)
     37        return kMinBufferSize;
     38    return std::min(size, kMaxBufferSize);
     39}
     40
     41
     42// #pragma mark - BZstdCompressionParameters
     43
     44
     45BZstdCompressionParameters::BZstdCompressionParameters(
     46    int compressionLevel)
     47    :
     48    BCompressionParameters(),
     49    fCompressionLevel(compressionLevel),
     50    fBufferSize(kDefaultBufferSize)
     51{
     52}
     53
     54
     55BZstdCompressionParameters::~BZstdCompressionParameters()
     56{
     57}
     58
     59
     60int32
     61BZstdCompressionParameters::CompressionLevel() const
     62{
     63    return fCompressionLevel;
     64}
     65
     66
     67void
     68BZstdCompressionParameters::SetCompressionLevel(int32 level)
     69{
     70    fCompressionLevel = level;
     71}
     72
     73
     74size_t
     75BZstdCompressionParameters::BufferSize() const
     76{
     77    return fBufferSize;
     78}
     79
     80
     81void
     82BZstdCompressionParameters::SetBufferSize(size_t size)
     83{
     84    fBufferSize = sanitize_buffer_size(size);
     85}
     86
     87
     88// #pragma mark - BZstdDecompressionParameters
     89
     90
     91BZstdDecompressionParameters::BZstdDecompressionParameters()
     92    :
     93    BDecompressionParameters(),
     94    fBufferSize(kDefaultBufferSize)
     95{
     96}
     97
     98
     99BZstdDecompressionParameters::~BZstdDecompressionParameters()
     100{
     101}
     102
     103
     104size_t
     105BZstdDecompressionParameters::BufferSize() const
     106{
     107    return fBufferSize;
     108}
     109
     110
     111void
     112BZstdDecompressionParameters::SetBufferSize(size_t size)
     113{
     114    fBufferSize = sanitize_buffer_size(size);
     115}
     116
     117
     118// #pragma mark - CompressionStrategy
     119
     120
     121#ifdef B_ZSTD_COMPRESSION_SUPPORT
     122
     123
     124struct BZstdCompressionAlgorithm::CompressionStrategy {
     125    typedef BZstdCompressionParameters Parameters;
     126
     127    static const bool kNeedsFinalFlush = true;
     128
     129    static size_t Init(ZSTD_CStream **stream,
     130        const BZstdCompressionParameters* parameters)
     131    {
     132        int32 compressionLevel = B_ZSTD_COMPRESSION_DEFAULT;
     133        if (parameters != NULL) {
     134            compressionLevel = parameters->CompressionLevel();
     135        }
     136
     137        *stream = ZSTD_createCStream();
     138        return ZSTD_initCStream(*stream, compressionLevel);
     139    }
     140
     141    static void Uninit(ZSTD_CStream *stream)
     142    {
     143        ZSTD_freeCStream(stream);
     144    }
     145
     146    static size_t Process(ZSTD_CStream *stream, ZSTD_inBuffer *input,
     147        ZSTD_outBuffer *output, bool flush)
     148    {
     149        return ZSTD_compressStream(stream, output, input);
     150    }
     151};
     152
     153
     154#endif  // B_ZSTD_COMPRESSION_SUPPORT
     155
     156
     157// #pragma mark - DecompressionStrategy
     158
     159
     160struct BZstdCompressionAlgorithm::DecompressionStrategy {
     161    typedef BZstdDecompressionParameters Parameters;
     162
     163    static size_t Init(ZSTD_DStream **stream,
     164        const BZstdDecompressionParameters* /*parameters*/)
     165    {
     166        *stream = ZSTD_createDStream();
     167        return ZSTD_initDStream(*stream);
     168    }
     169
     170    static void Uninit(ZSTD_DStream *stream)
     171    {
     172        ZSTD_freeDStream(stream);
     173    }
     174
     175    static size_t Process(ZSTD_DStream *stream, ZSTD_inBuffer *input,
     176        ZSTD_outBuffer *output, bool flush)
     177    {
     178        return ZSTD_decompressStream(stream, output, input);
     179    }
     180
     181};
     182
     183
     184// #pragma mark - Stream
     185
     186
     187template<typename BaseClass, typename Strategy, typename StreamType>
     188struct BZstdCompressionAlgorithm::Stream : BaseClass {
     189    Stream(BDataIO* io)
     190        :
     191        BaseClass(io),
     192        fStreamInitialized(false)
     193    {
     194    }
     195
     196    ~Stream()
     197    {
     198        if (fStreamInitialized) {
     199            Strategy::Uninit(fStream);
     200        }
     201    }
     202
     203    status_t Init(const typename Strategy::Parameters* parameters)
     204    {
     205        status_t error = this->BaseClass::Init(
     206            parameters != NULL ? parameters->BufferSize() : kDefaultBufferSize);
     207        if (error != B_OK)
     208            return error;
     209
     210        size_t zstdError = Strategy::Init(&fStream, parameters);
     211        if (ZSTD_getErrorCode(zstdError) != ZSTD_error_no_error)
     212            return _TranslateZstdError(zstdError);
     213
     214        fStreamInitialized = true;
     215        return B_OK;
     216    }
     217
     218    virtual status_t ProcessData(const void* input, size_t inputSize,
     219        void* output, size_t outputSize, size_t& bytesConsumed,
     220        size_t& bytesProduced)
     221    {
     222        return _ProcessData(input, inputSize, output, outputSize,
     223            bytesConsumed, bytesProduced, false);
     224    }
     225
     226    virtual status_t FlushPendingData(void* output, size_t outputSize,
     227        size_t& bytesProduced)
     228    {
     229        size_t bytesConsumed;
     230        return _ProcessData(NULL, 0, output, outputSize,
     231            bytesConsumed, bytesProduced, true);
     232    }
     233
     234    template<typename BaseParameters>
     235    static status_t Create(BDataIO* io, BaseParameters* _parameters,
     236        BDataIO*& _stream)
     237    {
     238        const typename Strategy::Parameters* parameters
     239#ifdef _BOOT_MODE
     240            = static_cast<const typename Strategy::Parameters*>(_parameters);
     241#else
     242            = dynamic_cast<const typename Strategy::Parameters*>(_parameters);
     243#endif
     244        Stream* stream = new(std::nothrow) Stream(io);
     245        if (stream == NULL)
     246            return B_NO_MEMORY;
     247
     248        status_t error = stream->Init(parameters);
     249        if (error != B_OK) {
     250            delete stream;
     251            return error;
     252        }
     253
     254        _stream = stream;
     255        return B_OK;
     256    }
     257
     258private:
     259    status_t _ProcessData(const void* input, size_t inputSize,
     260        void* output, size_t outputSize, size_t& bytesConsumed,
     261        size_t& bytesProduced, bool flush)
     262    {
     263        inBuffer.src = input;
     264        inBuffer.size = inputSize;
     265        outBuffer.dst = output;
     266        outBuffer.size = outputSize;
     267
     268        size_t zstdError = Strategy::Process(fStream, &inBuffer, &outBuffer, flush);
     269        if (ZSTD_getErrorCode(zstdError) != ZSTD_error_no_error) {
     270            /*if (zstdError == Z_STREAM_END) {
     271                if (fStream.avail_in != 0)
     272                    return B_BAD_DATA;
     273            } else*/
     274                return _TranslateZstdError(zstdError);
     275        }
     276
     277        bytesConsumed = inBuffer.pos;
     278        bytesProduced = outBuffer.pos;
     279        return B_OK;
     280    }
     281
     282private:
     283    bool        fStreamInitialized;
     284    StreamType  *fStream;
     285    ZSTD_inBuffer inBuffer;
     286    ZSTD_outBuffer outBuffer;
     287};
     288
     289
     290// #pragma mark - BZstdCompressionAlgorithm
     291
     292
     293BZstdCompressionAlgorithm::BZstdCompressionAlgorithm()
     294    :
     295    BCompressionAlgorithm()
     296{
     297}
     298
     299
     300BZstdCompressionAlgorithm::~BZstdCompressionAlgorithm()
     301{
     302}
     303
     304
     305status_t
     306BZstdCompressionAlgorithm::CreateCompressingInputStream(BDataIO* input,
     307    const BCompressionParameters* parameters, BDataIO*& _stream)
     308{
     309#ifdef B_ZSTD_COMPRESSION_SUPPORT
     310    return Stream<BAbstractInputStream, CompressionStrategy, ZSTD_CStream>::Create(
     311        input, parameters, _stream);
     312#else
     313    return B_NOT_SUPPORTED;
     314#endif
     315}
     316
     317
     318status_t
     319BZstdCompressionAlgorithm::CreateCompressingOutputStream(BDataIO* output,
     320    const BCompressionParameters* parameters, BDataIO*& _stream)
     321{
     322#ifdef B_ZSTD_COMPRESSION_SUPPORT
     323    return Stream<BAbstractOutputStream, CompressionStrategy, ZSTD_CStream>::Create(
     324        output, parameters, _stream);
     325#else
     326    return B_NOT_SUPPORTED;
     327#endif
     328}
     329
     330
     331status_t
     332BZstdCompressionAlgorithm::CreateDecompressingInputStream(BDataIO* input,
     333    const BDecompressionParameters* parameters, BDataIO*& _stream)
     334{
     335    return Stream<BAbstractInputStream, DecompressionStrategy, ZSTD_DStream>::Create(
     336        input, parameters, _stream);
     337}
     338
     339
     340status_t
     341BZstdCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output,
     342    const BDecompressionParameters* parameters, BDataIO*& _stream)
     343{
     344    return Stream<BAbstractOutputStream, DecompressionStrategy, ZSTD_DStream>::Create(
     345        output, parameters, _stream);
     346}
     347
     348
     349status_t
     350BZstdCompressionAlgorithm::CompressBuffer(const void* input,
     351    size_t inputSize, void* output, size_t outputSize, size_t& _compressedSize,
     352    const BCompressionParameters* parameters)
     353{
     354#ifdef B_ZSTD_COMPRESSION_SUPPORT
     355    const BZstdCompressionParameters* zstdParameters
     356        = dynamic_cast<const BZstdCompressionParameters*>(parameters);
     357    int compressionLevel = zstdParameters != NULL
     358        ? zstdParameters->CompressionLevel()
     359        : B_ZSTD_COMPRESSION_DEFAULT;
     360
     361    size_t zstdError = ZSTD_compress(output, outputSize, input,
     362        inputSize, compressionLevel);
     363    if (ZSTD_isError(zstdError))
     364        return _TranslateZstdError(zstdError);
     365
     366    _compressedSize = zstdError;
     367    return B_OK;
     368#else
     369    return B_NOT_SUPPORTED;
     370#endif
     371}
     372
     373
     374status_t
     375BZstdCompressionAlgorithm::DecompressBuffer(const void* input,
     376    size_t inputSize, void* output, size_t outputSize,
     377    size_t& _uncompressedSize, const BDecompressionParameters* parameters)
     378{
     379    size_t zstdError = ZSTD_decompress(output, outputSize, input,
     380        inputSize);
     381    if (ZSTD_isError(zstdError))
     382        return _TranslateZstdError(zstdError);
     383
     384    _uncompressedSize = zstdError;
     385    return B_OK;
     386}
     387
     388
     389/*static*/ status_t
     390BZstdCompressionAlgorithm::_TranslateZstdError(size_t error)
     391{
     392    switch (ZSTD_getErrorCode(error)) {
     393        case ZSTD_error_no_error:
     394            return B_OK;
     395        case ZSTD_error_seekableIO:
     396            return B_BAD_VALUE;
     397        case ZSTD_error_corruption_detected:
     398        case ZSTD_error_checksum_wrong:
     399            return B_BAD_DATA;
     400        case ZSTD_error_version_unsupported:
     401            return B_BAD_VALUE;
     402        default:
     403            return B_ERROR;
     404    }
     405}
  • src/system/kernel/lib/Jamfile

    diff --git a/src/system/kernel/lib/Jamfile b/src/system/kernel/lib/Jamfile
    index 339945d..a6d7054 100644
    a b KernelMergeObject kernel_misc.o :  
    141141
    142142HaikuSubInclude arch $(TARGET_ARCH) ;
    143143HaikuSubInclude zlib ;
     144if [ FIsBuildFeatureEnabled zstd ] {
     145    HaikuSubInclude zstd ;
     146}
  • new file src/system/kernel/lib/zstd/Jamfile

    diff --git a/src/system/kernel/lib/zstd/Jamfile b/src/system/kernel/lib/zstd/Jamfile
    new file mode 100644
    index 0000000..2d4a5d2
    - +  
     1SubDir HAIKU_TOP src system kernel lib zstd ;
     2
     3local zstdSourceDirectory = [ BuildFeatureAttribute zstd : sources : path ] ;
     4UseHeaders [ FDirName $(zstdSourceDirectory) lib ] ;
     5UseHeaders [ FDirName $(zstdSourceDirectory) lib common ] ;
     6
     7local zstdCommonSources =
     8    error_private.c
     9    entropy_common.c fse_decompress.c zstd_common.c
     10    xxhash.c
     11    ;
     12local zstdDecSources =
     13    huf_decompress.c zstd_decompress.c
     14    ;
     15
     16LOCATE on [ FGristFiles $(zstdCommonSources) ] =
     17    [ FDirName $(zstdSourceDirectory) lib common ] ;
     18LOCATE on [ FGristFiles $(zstdDecSources) ] =
     19    [ FDirName $(zstdSourceDirectory) lib decompress ] ;
     20Depends [ FGristFiles $(zstdCommonSources) $(zstdDecSources) ]
     21    : [ BuildFeatureAttribute zstd : sources ] ;
     22
     23# Build zstd with PIC, such that it can be used by kernel add-ons (filesystems).
     24KernelStaticLibrary kernel_libzstd.a :
     25    $(zstdCommonSources) $(zstdDecSources)
     26    ;