1
0
Fork 0
arangodb/3rdParty/iresearch/core/utils/compression.hpp

231 lines
8.7 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// 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 <map>
// -----------------------------------------------------------------------------
// --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<bool(const string_ref&)>& 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