//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2019 ArangoDB GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Andrey Abramov //////////////////////////////////////////////////////////////////////////////// #ifndef IRESEARCH_COMPRESSION_H #define IRESEARCH_COMPRESSION_H #include "type_id.hpp" #include "memory.hpp" #include "noncopyable.hpp" #include // ----------------------------------------------------------------------------- // --SECTION-- compression definition // ----------------------------------------------------------------------------- #define DECLARE_COMPRESSION_TYPE() DECLARE_TYPE_ID(iresearch::compression::type_id) #define DEFINE_COMPRESSION_TYPE_NAMED(class_type, class_name) \ DEFINE_TYPE_ID(class_type, iresearch::compression::type_id) { \ static iresearch::compression::type_id type(class_name); \ return type; \ } #define DEFINE_COMPRESSION_TYPE(class_type) DEFINE_COMPRESSION_TYPE_NAMED(class_type, #class_type) // ----------------------------------------------------------------------------- // --SECTION-- compression registration // ----------------------------------------------------------------------------- #define REGISTER_COMPRESSION__(compression_name, compressor_factory, decompressor_factory, line, source) \ static iresearch::compression::compression_registrar compression_registrar ## _ ## line(compression_name::type(), compressor_factory, decompressor_factory, source) #define REGISTER_COMPRESSION_EXPANDER__(compression_name, compressor_factory, decompressor_factory, file, line) \ REGISTER_COMPRESSION__(compression_name, compressor_factory, decompressor_factory, line, file ":" TOSTRING(line)) #define REGISTER_COMPRESSION(compression_name, compressor_factory, decompressor_factory) \ REGISTER_COMPRESSION_EXPANDER__(compression_name, compressor_factory, decompressor_factory, __FILE__, __LINE__) NS_ROOT struct data_output; struct data_input; NS_BEGIN(compression) struct options { enum class Hint : byte_type { /// @brief use default compressor parameters DEFAULT = 0, /// @brief prefer speed over compression ratio SPEED, /// @brief prefer compression ratio over speed COMPRESSION }; /// @brief Hint hint{ Hint::DEFAULT }; options(Hint hint = Hint::DEFAULT) : hint(hint) { } }; //////////////////////////////////////////////////////////////////////////////// /// @class compressor //////////////////////////////////////////////////////////////////////////////// struct IRESEARCH_API compressor { DECLARE_SHARED_PTR(compressor); virtual ~compressor() = default; /// @note caller is allowed to modify data pointed by 'in' up to 'size' virtual bytes_ref compress(byte_type* in, size_t size, bstring& buf) = 0; /// @brief flush arbitrary payload relevant to compression virtual void flush(data_output& /*out*/) { /*NOOP*/ } }; //////////////////////////////////////////////////////////////////////////////// /// @class compressor //////////////////////////////////////////////////////////////////////////////// struct IRESEARCH_API decompressor { DECLARE_SHARED_PTR(decompressor); virtual ~decompressor() = default; /// @note caller is allowed to modify data pointed by 'src' up to 'src_size' /// @note caller is allowed to modify data pointed by 'dst' up to 'dst_size' virtual bytes_ref decompress(byte_type* src, size_t src_size, byte_type* dst, size_t dst_size) = 0; virtual bool prepare(data_input& /*in*/) { // NOOP return true; } }; //////////////////////////////////////////////////////////////////////////////// /// @class type_id //////////////////////////////////////////////////////////////////////////////// class IRESEARCH_API type_id : public irs::type_id, private util::noncopyable { public: type_id(const string_ref& name) NOEXCEPT : name_(name) { } operator const type_id*() const NOEXCEPT { return this; } const string_ref& name() const NOEXCEPT { return name_; } private: string_ref name_; }; typedef irs::compression::compressor::ptr(*compressor_factory_f)(const options&); typedef irs::compression::decompressor::ptr(*decompressor_factory_f)(); // ----------------------------------------------------------------------------- // --SECTION-- compression registration // ----------------------------------------------------------------------------- class IRESEARCH_API compression_registrar { public: compression_registrar(const compression::type_id& type, compressor_factory_f compressor_factory, decompressor_factory_f decompressor_factory, const char* source = nullptr); operator bool() const NOEXCEPT { return registered_; } private: bool registered_; }; //////////////////////////////////////////////////////////////////////////////// /// @brief checks whether an comopression with the specified name is registered //////////////////////////////////////////////////////////////////////////////// IRESEARCH_API bool exists(const string_ref& name, bool load_library = true); //////////////////////////////////////////////////////////////////////////////// /// @brief creates a compressor by name, or nullptr if not found //////////////////////////////////////////////////////////////////////////////// IRESEARCH_API compressor::ptr get_compressor( const string_ref& name, const options& opts, bool load_library = true) NOEXCEPT; //////////////////////////////////////////////////////////////////////////////// /// @brief creates a compressor by name, or nullptr if not found //////////////////////////////////////////////////////////////////////////////// inline compressor::ptr get_compressor( const type_id& type, const options& opts, bool load_library = true) NOEXCEPT { return get_compressor(type.name(), opts, load_library); } //////////////////////////////////////////////////////////////////////////////// /// @brief creates a decompressor by name, or nullptr if not found //////////////////////////////////////////////////////////////////////////////// IRESEARCH_API decompressor::ptr get_decompressor( const string_ref& name, bool load_library = true) NOEXCEPT; //////////////////////////////////////////////////////////////////////////////// /// @brief creates a decompressor by name, or nullptr if not found //////////////////////////////////////////////////////////////////////////////// inline decompressor::ptr get_decompressor( const type_id& type, bool load_library = true) NOEXCEPT { return get_decompressor(type.name(), load_library); } //////////////////////////////////////////////////////////////////////////////// /// @brief for static lib reference all known compressions in lib /// for shared lib NOOP /// no explicit call of fn is required, existence of fn is sufficient //////////////////////////////////////////////////////////////////////////////// IRESEARCH_API void init(); //////////////////////////////////////////////////////////////////////////////// /// @brief load all compressions from plugins directory //////////////////////////////////////////////////////////////////////////////// IRESEARCH_API void load_all(const std::string& path); //////////////////////////////////////////////////////////////////////////////// /// @brief visit all loaded compressions, terminate early if visitor returns false //////////////////////////////////////////////////////////////////////////////// IRESEARCH_API bool visit(const std::function& visitor); //////////////////////////////////////////////////////////////////////////////// /// @class raw /// @brief no compression //////////////////////////////////////////////////////////////////////////////// struct IRESEARCH_API raw { DECLARE_COMPRESSION_TYPE(); static void init(); static compression::compressor::ptr compressor(const options& /*opts*/) { return nullptr; } static compression::decompressor::ptr decompressor() { return nullptr; } }; // raw NS_END // compression NS_END #endif // IRESEARCH_COMPRESSION_H