diff --git a/cmake/libdwarfs.cmake b/cmake/libdwarfs.cmake index 786902b9..9e6e7704 100644 --- a/cmake/libdwarfs.cmake +++ b/cmake/libdwarfs.cmake @@ -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( $<$: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 diff --git a/include/dwarfs/block_compressor.h b/include/dwarfs/block_compressor.h index 0f69f89a..f940623e 100644 --- a/include/dwarfs/block_compressor.h +++ b/include/dwarfs/block_compressor.h @@ -21,29 +21,16 @@ #pragma once -#include -#include -#include #include -#include -#include -#include #include #include -#include -#include -#include -#include #include -#include #include #include 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_; }; -class block_decompressor { - public: - block_decompressor(compression_type type, std::span 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 metadata() const { return impl_->metadata(); } - - static shared_byte_buffer - decompress(compression_type type, std::span 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 metadata() const = 0; - - virtual compression_type type() const = 0; - }; - - private: - std::unique_ptr 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 const& options() const = 0; // TODO: span? - virtual std::set library_dependencies() const = 0; -}; - -class compression_factory : public compression_info { - public: - virtual std::unique_ptr - make_compressor(option_map& om) const = 0; - virtual std::unique_ptr - make_decompressor(std::span data) const = 0; -}; - -namespace detail { - -template -struct compression_factory_registrar; - -} // namespace detail - -class compression_registry { - public: - static compression_registry& instance(); - - std::unique_ptr - make_compressor(std::string_view spec) const; - std::unique_ptr - make_decompressor(compression_type type, std::span data) const; - - void for_each_algorithm( - std::function const& fn) - const; - - void register_factory(compression_type type, - std::unique_ptr&& factory); - - private: - compression_registry(); - ~compression_registry(); - - std::unordered_map> - factories_; - std::unordered_map names_; -}; - -namespace detail { - -#define DWARFS_COMPRESSION_TYPE_ENUMERATION_(name, value) \ - template <> \ - struct compression_factory_registrar { \ - 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::reg( \ - ::dwarfs::compression_registry& cr) { \ - cr.register_factory(factory::type, std::make_unique()); \ - } - } // namespace dwarfs diff --git a/include/dwarfs/block_decompressor.h b/include/dwarfs/block_decompressor.h new file mode 100644 index 00000000..92bf0742 --- /dev/null +++ b/include/dwarfs/block_decompressor.h @@ -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 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace dwarfs { + +class block_decompressor { + public: + block_decompressor(compression_type type, std::span 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 metadata() const { return impl_->metadata(); } + + static shared_byte_buffer + decompress(compression_type type, std::span 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 metadata() const = 0; + + virtual compression_type type() const = 0; + }; + + private: + std::unique_ptr impl_; +}; + +} // namespace dwarfs diff --git a/include/dwarfs/compressor_factory.h b/include/dwarfs/compressor_factory.h new file mode 100644 index 00000000..6022aadc --- /dev/null +++ b/include/dwarfs/compressor_factory.h @@ -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 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +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 options() const = 0; + virtual std::set library_dependencies() const = 0; +}; + +class compressor_factory : public compressor_info { + public: + virtual std::unique_ptr + create(option_map& om) const = 0; +}; + +} // namespace dwarfs diff --git a/include/dwarfs/compressor_registry.h b/include/dwarfs/compressor_registry.h new file mode 100644 index 00000000..ca41c51f --- /dev/null +++ b/include/dwarfs/compressor_registry.h @@ -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 . + */ + +#pragma once + +#include + +namespace dwarfs { + +class compressor_registry final : public detail::compressor_registry_base { + public: + static compressor_registry& instance(); + + std::unique_ptr create(std::string_view spec) const; + + private: + compressor_registry(); + ~compressor_registry(); +}; + +} // namespace dwarfs diff --git a/include/dwarfs/decompressor_factory.h b/include/dwarfs/decompressor_factory.h new file mode 100644 index 00000000..6b9d6507 --- /dev/null +++ b/include/dwarfs/decompressor_factory.h @@ -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 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +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 library_dependencies() const = 0; +}; + +class decompressor_factory : public decompressor_info { + public: + virtual std::unique_ptr + create(std::span data) const = 0; +}; + +} // namespace dwarfs diff --git a/include/dwarfs/decompressor_registry.h b/include/dwarfs/decompressor_registry.h new file mode 100644 index 00000000..bb4b06c6 --- /dev/null +++ b/include/dwarfs/decompressor_registry.h @@ -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 . + */ + +#pragma once + +#include + +namespace dwarfs { + +class decompressor_registry final : public detail::decompressor_registry_base { + public: + static decompressor_registry& instance(); + + std::unique_ptr + create(compression_type type, std::span data) const; + + private: + decompressor_registry(); + ~decompressor_registry(); +}; + +} // namespace dwarfs diff --git a/include/dwarfs/detail/compression_registry.h b/include/dwarfs/detail/compression_registry.h new file mode 100644 index 00000000..e4803cf7 --- /dev/null +++ b/include/dwarfs/detail/compression_registry.h @@ -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 . + */ + +#pragma once + +#include +#include +#include + +#include +#include + +namespace dwarfs { + +class library_dependencies; + +namespace detail { + +template +struct compression_registrar; + +class compression_registry_base { + protected: + void register_name(compression_type type, std::string_view name); + + std::unordered_map names_; +}; + +template +class compression_registry : public compression_registry_base { + public: + compression_registry(); + + void register_factory(compression_type type, + std::unique_ptr&& factory); + + void for_each_algorithm( + std::function const& fn) const; + + void add_library_dependencies(library_dependencies& deps) const; + + protected: + template + void do_register(); + + FactoryT const& get_factory(compression_type type) const; + + private: + std::unordered_map> + factories_; +}; + +using compressor_registry_base = + compression_registry; +using decompressor_registry_base = + compression_registry; + +#define DWARFS_DETAIL_COMP_REGISTRAR_(type, name, value) \ + template <> \ + struct compression_registrar { \ + static std::unique_ptr 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::detail::compression_registrar::reg() { \ + return std::make_unique(); \ + } + +#define REGISTER_DECOMPRESSOR_FACTORY(factory) \ + std::unique_ptr \ + dwarfs::detail::compression_registrar::reg() { \ + return std::make_unique(); \ + } diff --git a/src/block_compressor.cpp b/src/block_compressor.cpp index e0f5e2b3..629ee698 100644 --- a/src/block_compressor.cpp +++ b/src/block_compressor.cpp @@ -19,150 +19,13 @@ * along with dwarfs. If not, see . */ -#include -#include -#include -#include - -#include -#include -#include - #include -#include -#include -#include -#include -#include +#include 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 data) { - impl_ = compression_registry::instance().make_decompressor(type, data); -} - -shared_byte_buffer -block_decompressor::decompress(compression_type type, - std::span 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&& factory) { - auto name = factory->name(); - - if (!factories_.emplace(type, std::move(factory)).second) { - std::cerr << "compression factory type conflict (" << name << ", " - << static_cast(type) << ")\n"; - ::abort(); - } - - if (!names_.emplace(name, type).second) { - std::cerr << "compression factory name conflict (" << name << ", " - << static_cast(type) << ")\n"; - ::abort(); - } -} - -std::unique_ptr -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 -compression_registry::make_decompressor(compression_type type, - std::span 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 const& fn) - const { - auto types = factories_ | ranges::views::keys | ranges::to; - - 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::reg(*this); -#ifdef DWARFS_HAVE_LIBBROTLI - compression_factory_registrar::reg(*this); -#endif -#ifdef DWARFS_HAVE_FLAC - compression_factory_registrar::reg(*this); -#endif -#ifdef DWARFS_HAVE_LIBLZ4 - compression_factory_registrar::reg(*this); - compression_factory_registrar::reg(*this); -#endif -#ifdef DWARFS_HAVE_LIBLZMA - compression_factory_registrar::reg(*this); -#endif -#ifdef DWARFS_HAVE_RICEPP - compression_factory_registrar::reg(*this); -#endif -#ifdef DWARFS_HAVE_LIBZSTD - compression_factory_registrar::reg(*this); -#endif -} - -compression_registry::~compression_registry() = default; - } // namespace dwarfs diff --git a/src/block_decompressor.cpp b/src/block_decompressor.cpp new file mode 100644 index 00000000..90585d8c --- /dev/null +++ b/src/block_decompressor.cpp @@ -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 . + */ + +#include +#include +#include +#include + +namespace dwarfs { + +block_decompressor::block_decompressor(compression_type type, + std::span data) { + impl_ = decompressor_registry::instance().create(type, data); +} + +shared_byte_buffer +block_decompressor::decompress(compression_type type, + std::span 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 diff --git a/src/compression/base.h b/src/compression/base.h index 51956faa..81c742ee 100644 --- a/src/compression/base.h +++ b/src/compression/base.h @@ -19,7 +19,7 @@ * along with dwarfs. If not, see . */ -#include +#include namespace dwarfs { diff --git a/src/compression/brotli.cpp b/src/compression/brotli.cpp index f6b95282..c06d18ad 100644 --- a/src/compression/brotli.cpp +++ b/src/compression/brotli.cpp @@ -26,6 +26,8 @@ #include +#include +#include #include #include #include @@ -152,58 +154,73 @@ class brotli_block_decompressor final : public block_decompressor_base { decoder_; }; -class brotli_compression_factory : public compression_factory { +template +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 { + 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 const& options() const override { return options_; } + std::span options() const override { return options_; } std::set library_dependencies() const override { return {fmt::format("libbrotlienc-{}", - version_string(::BrotliEncoderVersion())), - fmt::format("libbrotlidec-{}", - version_string(::BrotliDecoderVersion()))}; + version_string(::BrotliEncoderVersion()))}; } std::unique_ptr - make_compressor(option_map& om) const override { + create(option_map& om) const override { return std::make_unique( om.get("quality", BROTLI_DEFAULT_QUALITY), om.get("lgwin", BROTLI_DEFAULT_WINDOW)); } + private: + std::vector 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 { + 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 library_dependencies() const override { + return {fmt::format("libbrotlidec-{}", + version_string(::BrotliDecoderVersion()))}; + } + std::unique_ptr - make_decompressor(std::span data) const override { + create(std::span data) const override { return std::make_unique(data); } - - private: - static std::string version_string(uint32_t hex) { - return fmt::format("{}.{}.{}", hex >> 24, (hex >> 12) & 0xFFF, hex & 0xFFF); - } - - std::vector const options_; }; } // namespace -REGISTER_COMPRESSION_FACTORY(brotli_compression_factory) +REGISTER_COMPRESSOR_FACTORY(brotli_compressor_factory) +REGISTER_DECOMPRESSOR_FACTORY(brotli_decompressor_factory) } // namespace dwarfs diff --git a/src/compression/flac.cpp b/src/compression/flac.cpp index a92240da..709a9760 100644 --- a/src/compression/flac.cpp +++ b/src/compression/flac.cpp @@ -32,7 +32,8 @@ #include -#include +#include +#include #include #include #include @@ -477,15 +478,10 @@ class flac_block_decompressor final : public block_decompressor_base { std::unique_ptr decoder_; }; -class flac_compression_factory : public compression_factory { +template +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 const& options() const override { return options_; } - std::set library_dependencies() const override { return {fmt::format("libFLAC++-{}", ::FLAC__VERSION_STRING)}; } +}; + +class flac_compressor_factory final + : public flac_compression_info { + public: + std::span options() const override { return options_; } std::unique_ptr - make_compressor(option_map& om) const override { + create(option_map& om) const override { return std::make_unique( om.get("level", 5), om.get("exhaustive", false)); } + private: + std::vector const options_{ + fmt::format("level=[0..8]"), + fmt::format("exhaustive"), + }; +}; + +class flac_decompressor_factory final + : public flac_compression_info { + public: std::unique_ptr - make_decompressor(std::span data) const override { + create(std::span data) const override { return std::make_unique(data); } - - private: - std::vector const options_; }; } // namespace -REGISTER_COMPRESSION_FACTORY(flac_compression_factory) +REGISTER_COMPRESSOR_FACTORY(flac_compressor_factory) +REGISTER_DECOMPRESSOR_FACTORY(flac_decompressor_factory) } // namespace dwarfs diff --git a/src/compression/lz4.cpp b/src/compression/lz4.cpp index 99351add..468f1738 100644 --- a/src/compression/lz4.cpp +++ b/src/compression/lz4.cpp @@ -24,7 +24,9 @@ #include +#include #include +#include #include #include #include @@ -153,77 +155,87 @@ class lz4_block_decompressor final : public block_decompressor_base { std::string error_; }; -class lz4_compression_factory : public compression_factory { +template +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 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 library_dependencies() const override { return {fmt::format("liblz4-{}", ::LZ4_versionString())}; } - - std::unique_ptr - make_compressor(option_map&) const override { - return std::make_unique>(); - } - - std::unique_ptr - make_decompressor(std::span data) const override { - return std::make_unique(data); - } - - private: - std::vector const options_{}; }; -class lz4hc_compression_factory : public compression_factory { +class lz4_compressor_factory final + : public lz4_compression_info { public: - static constexpr compression_type type{compression_type::LZ4HC}; + std::span 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 create(option_map&) const override { + return std::make_unique>(); } +}; - std::vector const& options() const override { return options_; } - - std::set library_dependencies() const override { - return {fmt::format("liblz4-{}", ::LZ4_versionString())}; +class lz4_decompressor_factory final + : public lz4_compression_info { + public: + std::unique_ptr + create(std::span data) const override { + return std::make_unique(data); } +}; + +class lz4hc_compressor_factory final + : public lz4_compression_info { + public: + std::span options() const override { return options_; } std::unique_ptr - make_compressor(option_map& om) const override { + create(option_map& om) const override { return std::make_unique>( om.get("level", LZ4HC_CLEVEL_DEFAULT)); } + private: + std::vector const options_{ + fmt::format("level=[{}..{}]", 0, LZ4HC_CLEVEL_MAX)}; +}; + +class lz4hc_decompressor_factory final + : public lz4_compression_info { + public: std::unique_ptr - make_decompressor(std::span data) const override { + create(std::span data) const override { return std::make_unique(data); } - - private: - std::vector 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 diff --git a/src/compression/lzma.cpp b/src/compression/lzma.cpp index f0ca1c69..9506e6e9 100644 --- a/src/compression/lzma.cpp +++ b/src/compression/lzma.cpp @@ -31,6 +31,8 @@ #include #include +#include +#include #include #include #include @@ -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 +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 const& options() const override { return options_; } - std::set library_dependencies() const override { return {fmt::format("liblzma-{}", ::lzma_version_string())}; } +}; + +class lzma_compressor_factory final + : public lzma_compression_info { + public: + std::span options() const override { return options_; } std::unique_ptr - make_compressor(option_map& om) const override { + create(option_map& om) const override { return std::make_unique(om); } - std::unique_ptr - make_decompressor(std::span data) const override { - return std::make_unique(data); - } - private: std::vector 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 { + public: + std::unique_ptr + create(std::span data) const override { + return std::make_unique(data); + } +}; + } // namespace -REGISTER_COMPRESSION_FACTORY(lzma_compression_factory) +REGISTER_COMPRESSOR_FACTORY(lzma_compressor_factory) +REGISTER_DECOMPRESSOR_FACTORY(lzma_decompressor_factory) } // namespace dwarfs diff --git a/src/compression/null.cpp b/src/compression/null.cpp index 10069377..d52e3eae 100644 --- a/src/compression/null.cpp +++ b/src/compression/null.cpp @@ -23,6 +23,8 @@ #include +#include +#include #include #include #include @@ -90,7 +92,8 @@ class null_block_decompressor final : public block_decompressor_base { std::span data_; }; -class null_compression_factory : public compression_factory { +template +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 const& options() const override { return options_; } - std::set library_dependencies() const override { return {}; } +}; - std::unique_ptr - make_compressor(option_map&) const override { +class null_compressor_factory final + : public null_compression_info { + public: + std::span options() const override { return {}; } + + std::unique_ptr create(option_map&) const override { return std::make_unique(); } +}; +class null_decompressor_factory final + : public null_compression_info { + public: std::unique_ptr - make_decompressor(std::span data) const override { + create(std::span data) const override { return std::make_unique(data); } - - private: - std::vector const options_{}; }; } // namespace -REGISTER_COMPRESSION_FACTORY(null_compression_factory) +REGISTER_COMPRESSOR_FACTORY(null_compressor_factory) +REGISTER_DECOMPRESSOR_FACTORY(null_decompressor_factory) } // namespace dwarfs diff --git a/src/compression/ricepp.cpp b/src/compression/ricepp.cpp index 2fb68f2e..2e3dd941 100644 --- a/src/compression/ricepp.cpp +++ b/src/compression/ricepp.cpp @@ -27,7 +27,8 @@ #include -#include +#include +#include #include #include #include @@ -241,15 +242,11 @@ class ricepp_block_decompressor final : public block_decompressor_base { std::unique_ptr> codec_; }; -class ricepp_compression_factory : public compression_factory { +template +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 const& options() const override { return options_; } - std::set library_dependencies() const override { return {}; } +}; + +class ricepp_compressor_factory final + : public ricepp_compression_info { + public: + std::span options() const override { return options_; } std::unique_ptr - make_compressor(option_map& om) const override { + create(option_map& om) const override { return std::make_unique( om.get("block_size", 128)); } + private: + std::vector const options_{ + fmt::format("block_size=[{}..{}]", 16, 512), + }; +}; + +class ricepp_decompressor_factory final + : public ricepp_compression_info { + public: std::unique_ptr - make_decompressor(std::span data) const override { + create(std::span data) const override { return std::make_unique(data); } - - private: - std::vector const options_; }; } // namespace -REGISTER_COMPRESSION_FACTORY(ricepp_compression_factory) +REGISTER_COMPRESSOR_FACTORY(ricepp_compressor_factory) +REGISTER_DECOMPRESSOR_FACTORY(ricepp_decompressor_factory) } // namespace dwarfs diff --git a/src/compression/zstd.cpp b/src/compression/zstd.cpp index 5a90d7ac..37a6f860 100644 --- a/src/compression/zstd.cpp +++ b/src/compression/zstd.cpp @@ -25,6 +25,8 @@ #include +#include +#include #include #include #include @@ -158,14 +160,11 @@ class zstd_block_decompressor final : public block_decompressor_base { std::string error_; }; -class zstd_compression_factory : public compression_factory { +template +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 const& options() const override { return options_; } - std::set library_dependencies() const override { return {fmt::format("libzstd-{}", ::ZSTD_versionString())}; } +}; + +class zstd_compressor_factory final + : public zstd_compression_info { + public: + std::span options() const override { return options_; } std::unique_ptr - make_compressor(option_map& om) const override { + create(option_map& om) const override { return std::make_unique( om.get("level", ZSTD_maxCLevel())); } + private: + std::vector const options_{ + fmt::format("level=[{}..{}]", ZSTD_MIN_LEVEL, ZSTD_maxCLevel())}; +}; + +class zstd_decompressor_factory final + : public zstd_compression_info { + public: std::unique_ptr - make_decompressor(std::span data) const override { + create(std::span data) const override { return std::make_unique(data); } - - private: - std::vector const options_; }; } // namespace -REGISTER_COMPRESSION_FACTORY(zstd_compression_factory) +REGISTER_COMPRESSOR_FACTORY(zstd_compressor_factory) +REGISTER_DECOMPRESSOR_FACTORY(zstd_decompressor_factory) } // namespace dwarfs diff --git a/src/compression_registry.cpp b/src/compression_registry.cpp new file mode 100644 index 00000000..fbbbb20e --- /dev/null +++ b/src/compression_registry.cpp @@ -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 . + */ + +#include +#include +#include + +#include + +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(type) << ")\n"; + ::abort(); + } +} + +} // namespace dwarfs::detail diff --git a/src/compression_registry.h b/src/compression_registry.h new file mode 100644 index 00000000..098dcd5d --- /dev/null +++ b/src/compression_registry.h @@ -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 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace dwarfs::detail { + +template +void compression_registry::register_factory( + compression_type type, std::unique_ptr&& 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(type) << ")\n"; + ::abort(); + } +} + +template +void compression_registry::for_each_algorithm( + std::function const& fn) const { + auto types = factories_ | ranges::views::keys | ranges::to; + + ranges::sort(types); + + for (auto type : types) { + fn(type, *factories_.at(type)); + } +} + +template +void compression_registry::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 +template +void compression_registry::do_register() { + this->register_factory(Type, compression_registrar::reg()); +} + +template +FactoryT const& compression_registry::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 +compression_registry::compression_registry() { + using namespace ::dwarfs::detail; + using enum compression_type; + + do_register(); +#ifdef DWARFS_HAVE_LIBBROTLI + do_register(); +#endif +#ifdef DWARFS_HAVE_FLAC + do_register(); +#endif +#ifdef DWARFS_HAVE_LIBLZ4 + do_register(); + do_register(); +#endif +#ifdef DWARFS_HAVE_LIBLZMA + do_register(); +#endif +#ifdef DWARFS_HAVE_RICEPP + do_register(); +#endif +#ifdef DWARFS_HAVE_LIBZSTD + do_register(); +#endif +} + +} // namespace dwarfs::detail diff --git a/src/compressor_registry.cpp b/src/compressor_registry.cpp new file mode 100644 index 00000000..aaf47899 --- /dev/null +++ b/src/compressor_registry.cpp @@ -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 . + */ + +#include +#include +#include + +#include "compression_registry.h" + +namespace dwarfs { + +namespace detail { + +template class compression_registry; + +} // 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 +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 diff --git a/src/decompressor_registry.cpp b/src/decompressor_registry.cpp new file mode 100644 index 00000000..83ac52b6 --- /dev/null +++ b/src/decompressor_registry.cpp @@ -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 . + */ + +#include +#include +#include + +#include "compression_registry.h" + +namespace dwarfs { + +namespace detail { + +template class compression_registry; + +} // 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 +decompressor_registry::create(compression_type type, + std::span data) const { + return get_factory(type).create(data); +} + +} // namespace dwarfs diff --git a/src/library_dependencies.cpp b/src/library_dependencies.cpp index 30aa3ddb..7a300303 100644 --- a/src/library_dependencies.cpp +++ b/src/library_dependencies.cpp @@ -31,7 +31,6 @@ #include -#include #include 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 { diff --git a/src/reader/filesystem_v2.cpp b/src/reader/filesystem_v2.cpp index ed687bf2..297d3f4e 100644 --- a/src/reader/filesystem_v2.cpp +++ b/src/reader/filesystem_v2.cpp @@ -32,7 +32,7 @@ #include -#include +#include #include #include #include diff --git a/src/reader/internal/cached_block.cpp b/src/reader/internal/cached_block.cpp index fab16ad0..00f17395 100644 --- a/src/reader/internal/cached_block.cpp +++ b/src/reader/internal/cached_block.cpp @@ -26,7 +26,7 @@ #include #endif -#include +#include #include #include #include diff --git a/src/reader/internal/filesystem_parser.cpp b/src/reader/internal/filesystem_parser.cpp index e3cb7594..9d7cd9d7 100644 --- a/src/reader/internal/filesystem_parser.cpp +++ b/src/reader/internal/filesystem_parser.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/src/writer/filesystem_writer.cpp b/src/writer/filesystem_writer.cpp index dcca0e3f..b04206f5 100644 --- a/src/writer/filesystem_writer.cpp +++ b/src/writer/filesystem_writer.cpp @@ -34,7 +34,7 @@ #include -#include +#include #include #include #include diff --git a/test/flac_compressor_test.cpp b/test/flac_compressor_test.cpp index 6d481ff8..2fcda14e 100644 --- a/test/flac_compressor_test.cpp +++ b/test/flac_compressor_test.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/test/ricepp_compressor_test.cpp b/test/ricepp_compressor_test.cpp index 12ceb18f..49b642b6 100644 --- a/test/ricepp_compressor_test.cpp +++ b/test/ricepp_compressor_test.cpp @@ -37,6 +37,7 @@ #include #include +#include #include using namespace dwarfs; diff --git a/tools/src/dwarfs_main.cpp b/tools/src/dwarfs_main.cpp index ff7827f0..4a9d3376 100644 --- a/tools/src/dwarfs_main.cpp +++ b/tools/src/dwarfs_main.cpp @@ -82,6 +82,7 @@ #endif #include +#include #include #include #include @@ -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 diff --git a/tools/src/dwarfsck_main.cpp b/tools/src/dwarfsck_main.cpp index 0f30d31e..68aac5c9 100644 --- a/tools/src/dwarfsck_main.cpp +++ b/tools/src/dwarfsck_main.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/tools/src/dwarfsextract_main.cpp b/tools/src/dwarfsextract_main.cpp index 757a7cf6..04a5205b 100644 --- a/tools/src/dwarfsextract_main.cpp +++ b/tools/src/dwarfsextract_main.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -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" diff --git a/tools/src/mkdwarfs_main.cpp b/tools/src/mkdwarfs_main.cpp index b62010e0..7ce27fb4 100644 --- a/tools/src/mkdwarfs_main.cpp +++ b/tools/src/mkdwarfs_main.cpp @@ -56,8 +56,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -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; }