refactor: separate compression / decompression

This commit is contained in:
Marcus Holland-Moritz 2025-04-01 16:26:52 +02:00
parent dde5dcaead
commit 4e0ea2c165
33 changed files with 959 additions and 417 deletions

View File

@ -21,10 +21,9 @@ cmake_minimum_required(VERSION 3.28.0)
add_library(
dwarfs_common
src/block_compressor.cpp
src/block_compressor_parser.cpp
src/byte_buffer.cpp
src/checksum.cpp
src/compression_registry.cpp
src/conv.cpp
src/error.cpp
src/file_access_generic.cpp
@ -72,6 +71,21 @@ add_library(
$<$<BOOL:${ENABLE_RICEPP}>:src/compression/ricepp.cpp>
)
add_library(
dwarfs_compressor
src/block_compressor.cpp
src/block_compressor_parser.cpp
src/compressor_registry.cpp
)
add_library(
dwarfs_decompressor
src/block_decompressor.cpp
src/decompressor_registry.cpp
)
add_library(
dwarfs_reader
@ -170,8 +184,10 @@ add_cpp2_thrift_library(thrift/features.thrift
TARGET dwarfs_features_thrift OUTPUT_PATH dwarfs)
target_link_libraries(dwarfs_common PRIVATE dwarfs_folly_lite PkgConfig::LIBCRYPTO PkgConfig::XXHASH PkgConfig::ZSTD)
target_link_libraries(dwarfs_reader PUBLIC dwarfs_common)
target_link_libraries(dwarfs_writer PUBLIC dwarfs_common PkgConfig::ZSTD)
target_link_libraries(dwarfs_compressor PRIVATE dwarfs_common)
target_link_libraries(dwarfs_decompressor PRIVATE dwarfs_common)
target_link_libraries(dwarfs_reader PUBLIC dwarfs_common dwarfs_decompressor)
target_link_libraries(dwarfs_writer PUBLIC dwarfs_common dwarfs_compressor dwarfs_decompressor)
target_link_libraries(dwarfs_extractor PUBLIC dwarfs_reader)
target_link_libraries(dwarfs_rewrite PUBLIC dwarfs_reader dwarfs_writer)
@ -241,6 +257,8 @@ endif()
list(APPEND LIBDWARFS_TARGETS
dwarfs_common
dwarfs_compressor
dwarfs_decompressor
dwarfs_reader
dwarfs_writer
dwarfs_extractor

View File

@ -21,29 +21,16 @@
#pragma once
#include <cstdint>
#include <cstdio>
#include <functional>
#include <memory>
#include <optional>
#include <set>
#include <span>
#include <stdexcept>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>
#include <dwarfs/byte_buffer.h>
#include <dwarfs/byte_buffer_factory.h>
#include <dwarfs/compression.h>
#include <dwarfs/compression_constraints.h>
namespace dwarfs {
class option_map;
class bad_compression_ratio_error : public std::runtime_error {
public:
bad_compression_ratio_error()
@ -108,112 +95,4 @@ class block_compressor {
std::unique_ptr<impl> impl_;
};
class block_decompressor {
public:
block_decompressor(compression_type type, std::span<uint8_t const> data);
shared_byte_buffer start_decompression(mutable_byte_buffer target);
shared_byte_buffer start_decompression(byte_buffer_factory const& bbf);
bool decompress_frame(size_t frame_size = BUFSIZ) {
return impl_->decompress_frame(frame_size);
}
size_t uncompressed_size() const { return impl_->uncompressed_size(); }
compression_type type() const { return impl_->type(); }
std::optional<std::string> metadata() const { return impl_->metadata(); }
static shared_byte_buffer
decompress(compression_type type, std::span<uint8_t const> data);
class impl {
public:
virtual ~impl() = default;
virtual void start_decompression(mutable_byte_buffer target) = 0;
virtual bool decompress_frame(size_t frame_size) = 0;
virtual size_t uncompressed_size() const = 0;
virtual std::optional<std::string> metadata() const = 0;
virtual compression_type type() const = 0;
};
private:
std::unique_ptr<impl> impl_;
};
class compression_info {
public:
virtual ~compression_info() = default;
virtual std::string_view name() const = 0;
virtual std::string_view description() const = 0;
virtual std::vector<std::string> const& options() const = 0; // TODO: span?
virtual std::set<std::string> library_dependencies() const = 0;
};
class compression_factory : public compression_info {
public:
virtual std::unique_ptr<block_compressor::impl>
make_compressor(option_map& om) const = 0;
virtual std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const = 0;
};
namespace detail {
template <compression_type T>
struct compression_factory_registrar;
} // namespace detail
class compression_registry {
public:
static compression_registry& instance();
std::unique_ptr<block_compressor::impl>
make_compressor(std::string_view spec) const;
std::unique_ptr<block_decompressor::impl>
make_decompressor(compression_type type, std::span<uint8_t const> data) const;
void for_each_algorithm(
std::function<void(compression_type, compression_info const&)> const& fn)
const;
void register_factory(compression_type type,
std::unique_ptr<compression_factory const>&& factory);
private:
compression_registry();
~compression_registry();
std::unordered_map<compression_type,
std::unique_ptr<compression_factory const>>
factories_;
std::unordered_map<std::string, compression_type> names_;
};
namespace detail {
#define DWARFS_COMPRESSION_TYPE_ENUMERATION_(name, value) \
template <> \
struct compression_factory_registrar<compression_type::name> { \
static void reg(compression_registry&); \
};
#define DWARFS_NO_SEPARATOR_
DWARFS_COMPRESSION_TYPE_LIST(DWARFS_COMPRESSION_TYPE_ENUMERATION_,
DWARFS_NO_SEPARATOR_)
#undef DWARFS_COMPRESSION_TYPE_ENUMERATION_
#undef DWARFS_NO_SEPARATOR_
} // namespace detail
#define REGISTER_COMPRESSION_FACTORY(factory) \
void ::dwarfs::detail::compression_factory_registrar<factory::type>::reg( \
::dwarfs::compression_registry& cr) { \
cr.register_factory(factory::type, std::make_unique<factory>()); \
}
} // namespace dwarfs

View File

@ -0,0 +1,75 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstdint>
#include <cstdio>
#include <memory>
#include <optional>
#include <set>
#include <span>
#include <string>
#include <string_view>
#include <dwarfs/byte_buffer.h>
#include <dwarfs/byte_buffer_factory.h>
#include <dwarfs/compression.h>
namespace dwarfs {
class block_decompressor {
public:
block_decompressor(compression_type type, std::span<uint8_t const> data);
shared_byte_buffer start_decompression(mutable_byte_buffer target);
shared_byte_buffer start_decompression(byte_buffer_factory const& bbf);
bool decompress_frame(size_t frame_size = BUFSIZ) {
return impl_->decompress_frame(frame_size);
}
size_t uncompressed_size() const { return impl_->uncompressed_size(); }
compression_type type() const { return impl_->type(); }
std::optional<std::string> metadata() const { return impl_->metadata(); }
static shared_byte_buffer
decompress(compression_type type, std::span<uint8_t const> data);
class impl {
public:
virtual ~impl() = default;
virtual void start_decompression(mutable_byte_buffer target) = 0;
virtual bool decompress_frame(size_t frame_size) = 0;
virtual size_t uncompressed_size() const = 0;
virtual std::optional<std::string> metadata() const = 0;
virtual compression_type type() const = 0;
};
private:
std::unique_ptr<impl> impl_;
};
} // namespace dwarfs

View File

@ -0,0 +1,52 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <memory>
#include <set>
#include <span>
#include <string>
#include <string_view>
#include <dwarfs/block_compressor.h>
namespace dwarfs {
class option_map;
class compressor_info {
public:
virtual ~compressor_info() = default;
virtual std::string_view name() const = 0;
virtual std::string_view description() const = 0;
virtual std::span<std::string const> options() const = 0;
virtual std::set<std::string> library_dependencies() const = 0;
};
class compressor_factory : public compressor_info {
public:
virtual std::unique_ptr<block_compressor::impl>
create(option_map& om) const = 0;
};
} // namespace dwarfs

View File

@ -0,0 +1,39 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <dwarfs/detail/compression_registry.h>
namespace dwarfs {
class compressor_registry final : public detail::compressor_registry_base {
public:
static compressor_registry& instance();
std::unique_ptr<block_compressor::impl> create(std::string_view spec) const;
private:
compressor_registry();
~compressor_registry();
};
} // namespace dwarfs

View File

@ -0,0 +1,49 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <memory>
#include <set>
#include <span>
#include <string>
#include <string_view>
#include <dwarfs/block_decompressor.h>
namespace dwarfs {
class decompressor_info {
public:
virtual ~decompressor_info() = default;
virtual std::string_view name() const = 0;
virtual std::string_view description() const = 0;
virtual std::set<std::string> library_dependencies() const = 0;
};
class decompressor_factory : public decompressor_info {
public:
virtual std::unique_ptr<block_decompressor::impl>
create(std::span<uint8_t const> data) const = 0;
};
} // namespace dwarfs

View File

@ -0,0 +1,40 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <dwarfs/detail/compression_registry.h>
namespace dwarfs {
class decompressor_registry final : public detail::decompressor_registry_base {
public:
static decompressor_registry& instance();
std::unique_ptr<block_decompressor::impl>
create(compression_type type, std::span<uint8_t const> data) const;
private:
decompressor_registry();
~decompressor_registry();
};
} // namespace dwarfs

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <functional>
#include <string_view>
#include <unordered_map>
#include <dwarfs/compressor_factory.h>
#include <dwarfs/decompressor_factory.h>
namespace dwarfs {
class library_dependencies;
namespace detail {
template <typename FactoryT, compression_type Type>
struct compression_registrar;
class compression_registry_base {
protected:
void register_name(compression_type type, std::string_view name);
std::unordered_map<std::string, compression_type> names_;
};
template <typename FactoryT, typename InfoT>
class compression_registry : public compression_registry_base {
public:
compression_registry();
void register_factory(compression_type type,
std::unique_ptr<FactoryT const>&& factory);
void for_each_algorithm(
std::function<void(compression_type, InfoT const&)> const& fn) const;
void add_library_dependencies(library_dependencies& deps) const;
protected:
template <compression_type Type>
void do_register();
FactoryT const& get_factory(compression_type type) const;
private:
std::unordered_map<compression_type, std::unique_ptr<FactoryT const>>
factories_;
};
using compressor_registry_base =
compression_registry<compressor_factory, compressor_info>;
using decompressor_registry_base =
compression_registry<decompressor_factory, decompressor_info>;
#define DWARFS_DETAIL_COMP_REGISTRAR_(type, name, value) \
template <> \
struct compression_registrar<type##_factory, compression_type::name> { \
static std::unique_ptr<type##_factory> reg(); \
}
#define DWARFS_COMPRESSION_TYPE_ENUMERATION_(name, value) \
DWARFS_DETAIL_COMP_REGISTRAR_(compressor, name, value); \
DWARFS_DETAIL_COMP_REGISTRAR_(decompressor, name, value);
#define DWARFS_NO_SEPARATOR_
DWARFS_COMPRESSION_TYPE_LIST(DWARFS_COMPRESSION_TYPE_ENUMERATION_,
DWARFS_NO_SEPARATOR_)
#undef DWARFS_COMPRESSION_TYPE_ENUMERATION_
#undef DWARFS_NO_SEPARATOR_
} // namespace detail
} // namespace dwarfs
#define REGISTER_COMPRESSOR_FACTORY(factory) \
std::unique_ptr<dwarfs::compressor_factory> \
dwarfs::detail::compression_registrar<dwarfs::compressor_factory, \
factory::type>::reg() { \
return std::make_unique<factory>(); \
}
#define REGISTER_DECOMPRESSOR_FACTORY(factory) \
std::unique_ptr<dwarfs::decompressor_factory> \
dwarfs::detail::compression_registrar<dwarfs::decompressor_factory, \
factory::type>::reg() { \
return std::make_unique<factory>(); \
}

View File

@ -19,150 +19,13 @@
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <range/v3/algorithm/sort.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/map.hpp>
#include <dwarfs/block_compressor.h>
#include <dwarfs/config.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/option_map.h>
#include <dwarfs/vector_byte_buffer.h>
#include <dwarfs/compressor_registry.h>
namespace dwarfs {
block_compressor::block_compressor(std::string const& spec) {
impl_ = compression_registry::instance().make_compressor(spec);
impl_ = compressor_registry::instance().create(spec);
}
block_decompressor::block_decompressor(compression_type type,
std::span<uint8_t const> data) {
impl_ = compression_registry::instance().make_decompressor(type, data);
}
shared_byte_buffer
block_decompressor::decompress(compression_type type,
std::span<uint8_t const> data) {
block_decompressor bd(type, data);
auto target = vector_byte_buffer::create_reserve(bd.uncompressed_size());
bd.start_decompression(target);
bd.decompress_frame(bd.uncompressed_size());
return target.share();
}
shared_byte_buffer
block_decompressor::start_decompression(mutable_byte_buffer target) {
impl_->start_decompression(target);
target.freeze_location();
return target.share();
}
shared_byte_buffer
block_decompressor::start_decompression(byte_buffer_factory const& bbf) {
auto target = bbf.create_mutable_fixed_reserve(impl_->uncompressed_size());
return start_decompression(target);
}
compression_registry& compression_registry::instance() {
static compression_registry the_instance;
return the_instance;
}
void compression_registry::register_factory(
compression_type type,
std::unique_ptr<compression_factory const>&& factory) {
auto name = factory->name();
if (!factories_.emplace(type, std::move(factory)).second) {
std::cerr << "compression factory type conflict (" << name << ", "
<< static_cast<int>(type) << ")\n";
::abort();
}
if (!names_.emplace(name, type).second) {
std::cerr << "compression factory name conflict (" << name << ", "
<< static_cast<int>(type) << ")\n";
::abort();
}
}
std::unique_ptr<block_compressor::impl>
compression_registry::make_compressor(std::string_view spec) const {
option_map om(spec);
auto nit = names_.find(om.choice());
if (nit == names_.end()) {
DWARFS_THROW(runtime_error, "unknown compression: " + om.choice());
}
auto fit = factories_.find(nit->second);
assert(fit != factories_.end());
auto obj = fit->second->make_compressor(om);
om.report();
return obj;
}
std::unique_ptr<block_decompressor::impl>
compression_registry::make_decompressor(compression_type type,
std::span<uint8_t const> data) const {
auto fit = factories_.find(type);
if (fit == factories_.end()) {
DWARFS_THROW(runtime_error,
"unsupported compression type: " + get_compression_name(type));
}
return fit->second->make_decompressor(data);
}
void compression_registry::for_each_algorithm(
std::function<void(compression_type, compression_info const&)> const& fn)
const {
auto types = factories_ | ranges::views::keys | ranges::to<std::vector>;
ranges::sort(types);
for (auto type : types) {
fn(type, *factories_.at(type));
}
}
compression_registry::compression_registry() {
using namespace ::dwarfs::detail;
using enum compression_type;
compression_factory_registrar<NONE>::reg(*this);
#ifdef DWARFS_HAVE_LIBBROTLI
compression_factory_registrar<BROTLI>::reg(*this);
#endif
#ifdef DWARFS_HAVE_FLAC
compression_factory_registrar<FLAC>::reg(*this);
#endif
#ifdef DWARFS_HAVE_LIBLZ4
compression_factory_registrar<LZ4>::reg(*this);
compression_factory_registrar<LZ4HC>::reg(*this);
#endif
#ifdef DWARFS_HAVE_LIBLZMA
compression_factory_registrar<LZMA>::reg(*this);
#endif
#ifdef DWARFS_HAVE_RICEPP
compression_factory_registrar<RICEPP>::reg(*this);
#endif
#ifdef DWARFS_HAVE_LIBZSTD
compression_factory_registrar<ZSTD>::reg(*this);
#endif
}
compression_registry::~compression_registry() = default;
} // namespace dwarfs

View File

@ -0,0 +1,57 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <dwarfs/block_decompressor.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/vector_byte_buffer.h>
namespace dwarfs {
block_decompressor::block_decompressor(compression_type type,
std::span<uint8_t const> data) {
impl_ = decompressor_registry::instance().create(type, data);
}
shared_byte_buffer
block_decompressor::decompress(compression_type type,
std::span<uint8_t const> data) {
block_decompressor bd(type, data);
auto target = vector_byte_buffer::create_reserve(bd.uncompressed_size());
bd.start_decompression(target);
bd.decompress_frame(bd.uncompressed_size());
return target.share();
}
shared_byte_buffer
block_decompressor::start_decompression(mutable_byte_buffer target) {
impl_->start_decompression(target);
target.freeze_location();
return target.share();
}
shared_byte_buffer
block_decompressor::start_decompression(byte_buffer_factory const& bbf) {
auto target = bbf.create_mutable_fixed_reserve(impl_->uncompressed_size());
return start_decompression(target);
}
} // namespace dwarfs

View File

@ -19,7 +19,7 @@
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_decompressor.h>
namespace dwarfs {

View File

@ -26,6 +26,8 @@
#include <fmt/format.h>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/option_map.h>
@ -152,58 +154,73 @@ class brotli_block_decompressor final : public block_decompressor_base {
decoder_;
};
class brotli_compression_factory : public compression_factory {
template <typename Base>
class brotli_compression_info : public Base {
public:
static constexpr compression_type type{compression_type::BROTLI};
brotli_compression_factory()
: options_{
fmt::format("quality=[{}..{}]", BROTLI_MIN_QUALITY,
BROTLI_MAX_QUALITY),
fmt::format("lgwin=[{}..{}]", BROTLI_MIN_WINDOW_BITS, 30),
} {}
static constexpr auto type{compression_type::BROTLI};
std::string_view name() const override { return "brotli"; }
static std::string version_string(uint32_t hex) {
return fmt::format("{}.{}.{}", hex >> 24, (hex >> 12) & 0xFFF, hex & 0xFFF);
}
};
class brotli_compressor_factory final
: public brotli_compression_info<compressor_factory> {
public:
std::string_view description() const override {
static std::string const s_desc{
fmt::format("Brotli compression (encoder {}, decoder {})",
version_string(::BrotliEncoderVersion()),
version_string(::BrotliDecoderVersion()))};
fmt::format("Brotli compressor (encoder {})",
version_string(::BrotliEncoderVersion()))};
return s_desc;
}
std::vector<std::string> const& options() const override { return options_; }
std::span<std::string const> options() const override { return options_; }
std::set<std::string> library_dependencies() const override {
return {fmt::format("libbrotlienc-{}",
version_string(::BrotliEncoderVersion())),
fmt::format("libbrotlidec-{}",
version_string(::BrotliDecoderVersion()))};
version_string(::BrotliEncoderVersion()))};
}
std::unique_ptr<block_compressor::impl>
make_compressor(option_map& om) const override {
create(option_map& om) const override {
return std::make_unique<brotli_block_compressor>(
om.get<uint32_t>("quality", BROTLI_DEFAULT_QUALITY),
om.get<uint32_t>("lgwin", BROTLI_DEFAULT_WINDOW));
}
private:
std::vector<std::string> const options_{
fmt::format("quality=[{}..{}]", BROTLI_MIN_QUALITY, BROTLI_MAX_QUALITY),
fmt::format("lgwin=[{}..{}]", BROTLI_MIN_WINDOW_BITS, 30),
};
};
class brotli_decompressor_factory final
: public brotli_compression_info<decompressor_factory> {
public:
std::string_view description() const override {
static std::string const s_desc{
fmt::format("Brotli decompressor (decoder {})",
version_string(::BrotliDecoderVersion()))};
return s_desc;
}
std::set<std::string> library_dependencies() const override {
return {fmt::format("libbrotlidec-{}",
version_string(::BrotliDecoderVersion()))};
}
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
create(std::span<uint8_t const> data) const override {
return std::make_unique<brotli_block_decompressor>(data);
}
private:
static std::string version_string(uint32_t hex) {
return fmt::format("{}.{}.{}", hex >> 24, (hex >> 12) & 0xFFF, hex & 0xFFF);
}
std::vector<std::string> const options_;
};
} // namespace
REGISTER_COMPRESSION_FACTORY(brotli_compression_factory)
REGISTER_COMPRESSOR_FACTORY(brotli_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(brotli_decompressor_factory)
} // namespace dwarfs

View File

@ -32,7 +32,8 @@
#include <nlohmann/json.hpp>
#include <dwarfs/compression.h>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/option_map.h>
#include <dwarfs/pcm_sample_transformer.h>
@ -477,15 +478,10 @@ class flac_block_decompressor final : public block_decompressor_base {
std::unique_ptr<dwarfs_flac_stream_decoder> decoder_;
};
class flac_compression_factory : public compression_factory {
template <typename Base>
class flac_compression_info : public Base {
public:
static constexpr compression_type type{compression_type::FLAC};
flac_compression_factory()
: options_{
fmt::format("level=[0..8]"),
fmt::format("exhaustive"),
} {}
static constexpr auto type{compression_type::FLAC};
std::string_view name() const override { return "flac"; }
@ -495,29 +491,41 @@ class flac_compression_factory : public compression_factory {
return s_desc;
}
std::vector<std::string> const& options() const override { return options_; }
std::set<std::string> library_dependencies() const override {
return {fmt::format("libFLAC++-{}", ::FLAC__VERSION_STRING)};
}
};
class flac_compressor_factory final
: public flac_compression_info<compressor_factory> {
public:
std::span<std::string const> options() const override { return options_; }
std::unique_ptr<block_compressor::impl>
make_compressor(option_map& om) const override {
create(option_map& om) const override {
return std::make_unique<flac_block_compressor>(
om.get<uint32_t>("level", 5), om.get<bool>("exhaustive", false));
}
private:
std::vector<std::string> const options_{
fmt::format("level=[0..8]"),
fmt::format("exhaustive"),
};
};
class flac_decompressor_factory final
: public flac_compression_info<decompressor_factory> {
public:
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
create(std::span<uint8_t const> data) const override {
return std::make_unique<flac_block_decompressor>(data);
}
private:
std::vector<std::string> const options_;
};
} // namespace
REGISTER_COMPRESSION_FACTORY(flac_compression_factory)
REGISTER_COMPRESSOR_FACTORY(flac_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(flac_decompressor_factory)
} // namespace dwarfs

View File

@ -24,7 +24,9 @@
#include <fmt/format.h>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/conv.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/option_map.h>
@ -153,77 +155,87 @@ class lz4_block_decompressor final : public block_decompressor_base {
std::string error_;
};
class lz4_compression_factory : public compression_factory {
template <typename Base, compression_type Type>
class lz4_compression_info : public Base {
public:
static constexpr compression_type type{compression_type::LZ4};
static constexpr auto type{Type};
std::string_view name() const override { return "lz4"; }
std::string_view description() const override {
static std::string const s_desc{
fmt::format("LZ4 compression (liblz4 {})", ::LZ4_versionString())};
return s_desc;
std::string_view name() const override {
if constexpr (type == compression_type::LZ4HC) {
return "lz4hc";
} else {
return "lz4";
}
}
std::vector<std::string> const& options() const override { return options_; }
std::string_view description() const override {
static constexpr std::string_view codec = [] {
if constexpr (type == compression_type::LZ4HC) {
return "LZ4 HC";
} else {
return "LZ4";
}
}();
static std::string const s_desc{fmt::format("{} compression (liblz4 {})",
codec, ::LZ4_versionString())};
return s_desc;
}
std::set<std::string> library_dependencies() const override {
return {fmt::format("liblz4-{}", ::LZ4_versionString())};
}
std::unique_ptr<block_compressor::impl>
make_compressor(option_map&) const override {
return std::make_unique<lz4_block_compressor<lz4_compression_policy>>();
}
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
return std::make_unique<lz4_block_decompressor>(data);
}
private:
std::vector<std::string> const options_{};
};
class lz4hc_compression_factory : public compression_factory {
class lz4_compressor_factory final
: public lz4_compression_info<compressor_factory, compression_type::LZ4> {
public:
static constexpr compression_type type{compression_type::LZ4HC};
std::span<std::string const> options() const override { return {}; }
lz4hc_compression_factory()
: options_{fmt::format("level=[{}..{}]", 0, LZ4HC_CLEVEL_MAX)} {}
std::string_view name() const override { return "lz4hc"; }
std::string_view description() const override {
static std::string const s_desc{
fmt::format("LZ4 HC compression (liblz4 {})", ::LZ4_versionString())};
return s_desc;
std::unique_ptr<block_compressor::impl> create(option_map&) const override {
return std::make_unique<lz4_block_compressor<lz4_compression_policy>>();
}
};
std::vector<std::string> const& options() const override { return options_; }
std::set<std::string> library_dependencies() const override {
return {fmt::format("liblz4-{}", ::LZ4_versionString())};
class lz4_decompressor_factory final
: public lz4_compression_info<decompressor_factory, compression_type::LZ4> {
public:
std::unique_ptr<block_decompressor::impl>
create(std::span<uint8_t const> data) const override {
return std::make_unique<lz4_block_decompressor>(data);
}
};
class lz4hc_compressor_factory final
: public lz4_compression_info<compressor_factory, compression_type::LZ4HC> {
public:
std::span<std::string const> options() const override { return options_; }
std::unique_ptr<block_compressor::impl>
make_compressor(option_map& om) const override {
create(option_map& om) const override {
return std::make_unique<lz4_block_compressor<lz4hc_compression_policy>>(
om.get<int>("level", LZ4HC_CLEVEL_DEFAULT));
}
private:
std::vector<std::string> const options_{
fmt::format("level=[{}..{}]", 0, LZ4HC_CLEVEL_MAX)};
};
class lz4hc_decompressor_factory final
: public lz4_compression_info<decompressor_factory,
compression_type::LZ4HC> {
public:
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
create(std::span<uint8_t const> data) const override {
return std::make_unique<lz4_block_decompressor>(data);
}
private:
std::vector<std::string> const options_;
};
} // namespace
REGISTER_COMPRESSION_FACTORY(lz4_compression_factory)
REGISTER_COMPRESSION_FACTORY(lz4hc_compression_factory)
REGISTER_COMPRESSOR_FACTORY(lz4_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(lz4_decompressor_factory)
REGISTER_COMPRESSOR_FACTORY(lz4hc_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(lz4hc_decompressor_factory)
} // namespace dwarfs

View File

@ -31,6 +31,8 @@
#include <range/v3/view/join.hpp>
#include <range/v3/view/map.hpp>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/option_map.h>
@ -392,7 +394,8 @@ size_t lzma_block_decompressor::get_uncompressed_size(uint8_t const* data,
return usize;
}
class lzma_compression_factory : public compression_factory {
template <typename Base>
class lzma_compression_info : public Base {
public:
static constexpr compression_type type{compression_type::LZMA};
@ -404,22 +407,21 @@ class lzma_compression_factory : public compression_factory {
return s_desc;
}
std::vector<std::string> const& options() const override { return options_; }
std::set<std::string> library_dependencies() const override {
return {fmt::format("liblzma-{}", ::lzma_version_string())};
}
};
class lzma_compressor_factory final
: public lzma_compression_info<compressor_factory> {
public:
std::span<std::string const> options() const override { return options_; }
std::unique_ptr<block_compressor::impl>
make_compressor(option_map& om) const override {
create(option_map& om) const override {
return std::make_unique<lzma_block_compressor>(om);
}
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
return std::make_unique<lzma_block_decompressor>(data);
}
private:
std::vector<std::string> const options_{
"level=[0..9]",
@ -433,8 +435,18 @@ class lzma_compression_factory : public compression_factory {
};
};
class lzma_decompressor_factory final
: public lzma_compression_info<decompressor_factory> {
public:
std::unique_ptr<block_decompressor::impl>
create(std::span<uint8_t const> data) const override {
return std::make_unique<lzma_block_decompressor>(data);
}
};
} // namespace
REGISTER_COMPRESSION_FACTORY(lzma_compression_factory)
REGISTER_COMPRESSOR_FACTORY(lzma_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(lzma_decompressor_factory)
} // namespace dwarfs

View File

@ -23,6 +23,8 @@
#include <fmt/format.h>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/option_map.h>
@ -90,7 +92,8 @@ class null_block_decompressor final : public block_decompressor_base {
std::span<uint8_t const> data_;
};
class null_compression_factory : public compression_factory {
template <typename Base>
class null_compression_info : public Base {
public:
static constexpr compression_type type{compression_type::NONE};
@ -100,26 +103,31 @@ class null_compression_factory : public compression_factory {
return "no compression at all";
}
std::vector<std::string> const& options() const override { return options_; }
std::set<std::string> library_dependencies() const override { return {}; }
};
std::unique_ptr<block_compressor::impl>
make_compressor(option_map&) const override {
class null_compressor_factory final
: public null_compression_info<compressor_factory> {
public:
std::span<std::string const> options() const override { return {}; }
std::unique_ptr<block_compressor::impl> create(option_map&) const override {
return std::make_unique<null_block_compressor>();
}
};
class null_decompressor_factory final
: public null_compression_info<decompressor_factory> {
public:
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
create(std::span<uint8_t const> data) const override {
return std::make_unique<null_block_decompressor>(data);
}
private:
std::vector<std::string> const options_{};
};
} // namespace
REGISTER_COMPRESSION_FACTORY(null_compression_factory)
REGISTER_COMPRESSOR_FACTORY(null_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(null_decompressor_factory)
} // namespace dwarfs

View File

@ -27,7 +27,8 @@
#include <ricepp/ricepp.h>
#include <dwarfs/compression.h>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/option_map.h>
#include <dwarfs/varint.h>
@ -241,15 +242,11 @@ class ricepp_block_decompressor final : public block_decompressor_base {
std::unique_ptr<ricepp::codec_interface<uint16_t>> codec_;
};
class ricepp_compression_factory : public compression_factory {
template <typename Base>
class ricepp_compression_info : public Base {
public:
static constexpr compression_type type{compression_type::RICEPP};
ricepp_compression_factory()
: options_{
fmt::format("block_size=[{}..{}]", 16, 512),
} {}
std::string_view name() const override { return "ricepp"; }
std::string_view description() const override {
@ -257,27 +254,38 @@ class ricepp_compression_factory : public compression_factory {
return s_desc;
}
std::vector<std::string> const& options() const override { return options_; }
std::set<std::string> library_dependencies() const override { return {}; }
};
class ricepp_compressor_factory final
: public ricepp_compression_info<compressor_factory> {
public:
std::span<std::string const> options() const override { return options_; }
std::unique_ptr<block_compressor::impl>
make_compressor(option_map& om) const override {
create(option_map& om) const override {
return std::make_unique<ricepp_block_compressor>(
om.get<size_t>("block_size", 128));
}
private:
std::vector<std::string> const options_{
fmt::format("block_size=[{}..{}]", 16, 512),
};
};
class ricepp_decompressor_factory final
: public ricepp_compression_info<decompressor_factory> {
public:
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
create(std::span<uint8_t const> data) const override {
return std::make_unique<ricepp_block_decompressor>(data);
}
private:
std::vector<std::string> const options_;
};
} // namespace
REGISTER_COMPRESSION_FACTORY(ricepp_compression_factory)
REGISTER_COMPRESSOR_FACTORY(ricepp_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(ricepp_decompressor_factory)
} // namespace dwarfs

View File

@ -25,6 +25,8 @@
#include <fmt/format.h>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/option_map.h>
@ -158,14 +160,11 @@ class zstd_block_decompressor final : public block_decompressor_base {
std::string error_;
};
class zstd_compression_factory : public compression_factory {
template <typename Base>
class zstd_compression_info : public Base {
public:
static constexpr compression_type type{compression_type::ZSTD};
zstd_compression_factory()
: options_{
fmt::format("level=[{}..{}]", ZSTD_MIN_LEVEL, ZSTD_maxCLevel())} {}
std::string_view name() const override { return "zstd"; }
std::string_view description() const override {
@ -174,29 +173,39 @@ class zstd_compression_factory : public compression_factory {
return s_desc;
}
std::vector<std::string> const& options() const override { return options_; }
std::set<std::string> library_dependencies() const override {
return {fmt::format("libzstd-{}", ::ZSTD_versionString())};
}
};
class zstd_compressor_factory final
: public zstd_compression_info<compressor_factory> {
public:
std::span<std::string const> options() const override { return options_; }
std::unique_ptr<block_compressor::impl>
make_compressor(option_map& om) const override {
create(option_map& om) const override {
return std::make_unique<zstd_block_compressor>(
om.get<int>("level", ZSTD_maxCLevel()));
}
private:
std::vector<std::string> const options_{
fmt::format("level=[{}..{}]", ZSTD_MIN_LEVEL, ZSTD_maxCLevel())};
};
class zstd_decompressor_factory final
: public zstd_compression_info<decompressor_factory> {
public:
std::unique_ptr<block_decompressor::impl>
make_decompressor(std::span<uint8_t const> data) const override {
create(std::span<uint8_t const> data) const override {
return std::make_unique<zstd_block_decompressor>(data);
}
private:
std::vector<std::string> const options_;
};
} // namespace
REGISTER_COMPRESSION_FACTORY(zstd_compression_factory)
REGISTER_COMPRESSOR_FACTORY(zstd_compressor_factory)
REGISTER_DECOMPRESSOR_FACTORY(zstd_decompressor_factory)
} // namespace dwarfs

View File

@ -0,0 +1,39 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <iostream>
#include <string>
#include <dwarfs/detail/compression_registry.h>
namespace dwarfs::detail {
void compression_registry_base::register_name(compression_type type,
std::string_view name) {
if (!names_.emplace(std::string{name}, type).second) {
std::cerr << "compression factory name conflict (" << name << ", "
<< static_cast<int>(type) << ")\n";
::abort();
}
}
} // namespace dwarfs::detail

125
src/compression_registry.h Normal file
View File

@ -0,0 +1,125 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <algorithm>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <memory>
#include <vector>
#include <range/v3/algorithm/sort.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/map.hpp>
#include <dwarfs/config.h>
#include <dwarfs/library_dependencies.h>
#include <dwarfs/detail/compression_registry.h>
#include <dwarfs/fstypes.h>
namespace dwarfs::detail {
template <typename FactoryT, typename InfoT>
void compression_registry<FactoryT, InfoT>::register_factory(
compression_type type, std::unique_ptr<FactoryT const>&& factory) {
auto name = factory->name();
register_name(type, name);
if (!factories_.emplace(type, std::move(factory)).second) {
std::cerr << "compression factory type conflict (" << name << ", "
<< static_cast<int>(type) << ")\n";
::abort();
}
}
template <typename FactoryT, typename InfoT>
void compression_registry<FactoryT, InfoT>::for_each_algorithm(
std::function<void(compression_type, InfoT const&)> const& fn) const {
auto types = factories_ | ranges::views::keys | ranges::to<std::vector>;
ranges::sort(types);
for (auto type : types) {
fn(type, *factories_.at(type));
}
}
template <typename FactoryT, typename InfoT>
void compression_registry<FactoryT, InfoT>::add_library_dependencies(
library_dependencies& deps) const {
this->for_each_algorithm(
[&](compression_type, InfoT const& info) {
for (auto const& lib : info.library_dependencies()) {
deps.add_library(lib);
}
});
}
template <typename FactoryT, typename InfoT>
template <compression_type Type>
void compression_registry<FactoryT, InfoT>::do_register() {
this->register_factory(Type, compression_registrar<FactoryT, Type>::reg());
}
template <typename FactoryT, typename InfoT>
FactoryT const& compression_registry<FactoryT, InfoT>::get_factory(
compression_type type) const {
auto it = factories_.find(type);
if (it == factories_.end()) {
DWARFS_THROW(runtime_error,
"unsupported compression type: " + get_compression_name(type));
}
return *it->second;
}
template <typename FactoryT, typename InfoT>
compression_registry<FactoryT, InfoT>::compression_registry() {
using namespace ::dwarfs::detail;
using enum compression_type;
do_register<NONE>();
#ifdef DWARFS_HAVE_LIBBROTLI
do_register<BROTLI>();
#endif
#ifdef DWARFS_HAVE_FLAC
do_register<FLAC>();
#endif
#ifdef DWARFS_HAVE_LIBLZ4
do_register<LZ4>();
do_register<LZ4HC>();
#endif
#ifdef DWARFS_HAVE_LIBLZMA
do_register<LZMA>();
#endif
#ifdef DWARFS_HAVE_RICEPP
do_register<RICEPP>();
#endif
#ifdef DWARFS_HAVE_LIBZSTD
do_register<ZSTD>();
#endif
}
} // namespace dwarfs::detail

View File

@ -0,0 +1,60 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <dwarfs/compressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/option_map.h>
#include "compression_registry.h"
namespace dwarfs {
namespace detail {
template class compression_registry<compressor_factory, compressor_info>;
} // namespace detail
compressor_registry::compressor_registry() = default;
compressor_registry::~compressor_registry() = default;
compressor_registry& compressor_registry::instance() {
static compressor_registry the_instance;
return the_instance;
}
std::unique_ptr<block_compressor::impl>
compressor_registry::create(std::string_view spec) const {
option_map om(spec);
auto nit = names_.find(om.choice());
if (nit == names_.end()) {
DWARFS_THROW(runtime_error, "unknown compression: " + om.choice());
}
auto obj = get_factory(nit->second).create(om);
om.report();
return obj;
}
} // namespace dwarfs

View File

@ -0,0 +1,50 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include "compression_registry.h"
namespace dwarfs {
namespace detail {
template class compression_registry<decompressor_factory, decompressor_info>;
} // namespace detail
decompressor_registry::decompressor_registry() = default;
decompressor_registry::~decompressor_registry() = default;
decompressor_registry& decompressor_registry::instance() {
static decompressor_registry the_instance;
return the_instance;
}
std::unique_ptr<block_decompressor::impl>
decompressor_registry::create(compression_type type,
std::span<uint8_t const> data) const {
return get_factory(type).create(data);
}
} // namespace dwarfs

View File

@ -31,7 +31,6 @@
#include <dwarfs/config.h>
#include <dwarfs/block_compressor.h>
#include <dwarfs/library_dependencies.h>
namespace dwarfs {
@ -93,13 +92,6 @@ void library_dependencies::add_common_libraries() {
add_library("libboost", BOOST_VERSION, version_format::boost);
add_library("phmap", PHMAP_VERSION_MAJOR, PHMAP_VERSION_MINOR,
PHMAP_VERSION_PATCH);
compression_registry::instance().for_each_algorithm(
[this](compression_type, compression_info const& info) {
for (auto const& lib : info.library_dependencies()) {
add_library(lib);
}
});
}
std::string library_dependencies::as_string() const {

View File

@ -32,7 +32,7 @@
#include <fmt/format.h>
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_decompressor.h>
#include <dwarfs/error.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/history.h>

View File

@ -26,7 +26,7 @@
#include <sys/mman.h>
#endif
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_decompressor.h>
#include <dwarfs/error.h>
#include <dwarfs/logger.h>
#include <dwarfs/mmif.h>

View File

@ -22,6 +22,7 @@
#include <algorithm>
#include <array>
#include <cstring>
#include <functional>
#include <utility>
#include <version>

View File

@ -34,7 +34,7 @@
#include <folly/system/ThreadName.h>
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_decompressor.h>
#include <dwarfs/checksum.h>
#include <dwarfs/error.h>
#include <dwarfs/logger.h>

View File

@ -27,6 +27,7 @@
#include <nlohmann/json.hpp>
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_decompressor.h>
#include <dwarfs/pcm_sample_transformer.h>
#include <dwarfs/vector_byte_buffer.h>

View File

@ -37,6 +37,7 @@
#include <range/v3/view/concat.hpp>
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_decompressor.h>
#include <dwarfs/vector_byte_buffer.h>
using namespace dwarfs;

View File

@ -82,6 +82,7 @@
#endif
#include <dwarfs/conv.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/file_stat.h>
#include <dwarfs/fstypes.h>
@ -1159,8 +1160,13 @@ int op_rename(char const* from, char const* to, unsigned int flags) {
#endif
void usage(std::ostream& os, std::filesystem::path const& progname) {
auto extra_deps = [](library_dependencies& deps) {
decompressor_registry::instance().add_library_dependencies(deps);
};
os << tool::tool_header("dwarfs",
fmt::format(", fuse version {}", FUSE_USE_VERSION))
fmt::format(", fuse version {}", FUSE_USE_VERSION),
extra_deps)
#if !DWARFS_FUSE_LOWLEVEL
<< "USING HIGH-LEVEL FUSE API\n\n"
#endif

View File

@ -37,6 +37,7 @@
#include <dwarfs/checksum.h>
#include <dwarfs/config.h>
#include <dwarfs/conv.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/file_access.h>
#include <dwarfs/logger.h>
@ -256,7 +257,11 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) {
auto constexpr usage = "Usage: dwarfsck [OPTIONS...]\n";
if (vm.contains("help") or !vm.contains("input")) {
iol.out << tool::tool_header("dwarfsck") << usage << "\n" << opts << "\n";
auto extra_deps = [](library_dependencies& deps) {
decompressor_registry::instance().add_library_dependencies(deps);
};
iol.out << tool::tool_header("dwarfsck", extra_deps) << usage << "\n"
<< opts << "\n";
return 0;
}

View File

@ -27,6 +27,7 @@
#include <boost/program_options.hpp>
#include <dwarfs/config.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/glob_matcher.h>
#include <dwarfs/logger.h>
#include <dwarfs/mmap.h>
@ -143,6 +144,7 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
if (vm.contains("help") or !vm.contains("input")) {
auto extra_deps = [](library_dependencies& deps) {
utility::filesystem_extractor::add_library_dependencies(deps);
decompressor_registry::instance().add_library_dependencies(deps);
};
iol.out << tool::tool_header("dwarfsextract", extra_deps) << usage << "\n"

View File

@ -56,8 +56,10 @@
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_compressor_parser.h>
#include <dwarfs/checksum.h>
#include <dwarfs/compressor_registry.h>
#include <dwarfs/config.h>
#include <dwarfs/conv.h>
#include <dwarfs/decompressor_registry.h>
#include <dwarfs/error.h>
#include <dwarfs/file_access.h>
#include <dwarfs/integral_value_parser.h>
@ -700,6 +702,10 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
#endif
auto constexpr usage = "Usage: mkdwarfs [OPTIONS...]\n";
auto extra_deps = [](library_dependencies& deps) {
compressor_registry::instance().add_library_dependencies(deps);
decompressor_registry::instance().add_library_dependencies(deps);
};
if (vm.contains("long-help")) {
constexpr std::string_view block_data_hdr{"Block Data"};
@ -716,7 +722,8 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
std::string sep(30 + l_dc + l_sc + l_mc + l_or, '-');
iol.out << tool::tool_header("mkdwarfs") << usage << opts << "\n"
iol.out << tool::tool_header("mkdwarfs", extra_deps) << usage << opts
<< "\n"
<< "Compression level defaults:\n"
<< " " << sep << "\n"
<< fmt::format(" Level Block {:{}s} {:s} Inode\n",
@ -741,8 +748,8 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
iol.out << "\nCompression algorithms:\n";
compression_registry::instance().for_each_algorithm(
[&iol](compression_type, compression_info const& info) {
compressor_registry::instance().for_each_algorithm(
[&iol](compression_type, compressor_info const& info) {
iol.out << fmt::format(" {:9}{}\n", info.name(), info.description());
for (auto const& opt : info.options()) {
iol.out << fmt::format(" {}\n", opt);
@ -768,7 +775,7 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
if (vm.contains("help") or
!(vm.contains("input") or vm.contains("input-list")) or
(!vm.contains("output") and !vm.contains("debug-filter"))) {
iol.out << tool::tool_header("mkdwarfs") << usage << "\n"
iol.out << tool::tool_header("mkdwarfs", extra_deps) << usage << "\n"
<< basic_opts << "\n";
return 0;
}