blob: c4c338e620a094082fb5a5a7532b6414b9774c2b [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
**/
#ifndef QUICKSTEP_COMPRESSION_COMPRESSION_DICTIONARY_LITE_HPP_
#define QUICKSTEP_COMPRESSION_COMPRESSION_DICTIONARY_LITE_HPP_
#include <cstddef>
#include <cstdint>
#include <limits>
#include "types/Type.hpp"
#include "types/TypedValue.hpp"
#include "utility/Macros.hpp"
#include "glog/logging.h"
namespace quickstep {
/** \addtogroup Compression
* @{
*/
// In-memory format of a CompressionDictionary is as follows:
// std::uint32_t num_codes - number of codes/values stored in dictionary
// (excluding NULL)
// std::uint32_t null_code - a code representing a NULL value (equal to
// num_codes if NULL is present, or the maximum
// possible value of std::uint32_t if NULL is not
// present)
// For fixed-length types:
// array of num_codes values
// For variable-length types:
// array of num_codes offsets of variable-length values
// variable-length storage region, with values stored at offsets specified
// by previous array.
/**
* @brief A dictionary which maps short integer codes to typed values.
* @note Codes in a CompressionDictionaryLite compare in the same order as the
* underlying values.
**/
class CompressionDictionaryLite {
public:
/**
* @brief Constructor.
*
* @param type The type of values being compressed. LessComparison must be
* applicable to this Type.
* @param dictionary_memory The memory location of the physical dictionary.
* @param dictionary_memory_size The size (in bytes) of the physical
* dictionary at dictionary_memory.
**/
CompressionDictionaryLite(const Type &type,
const void *dictionary_memory,
const std::size_t dictionary_memory_size);
virtual ~CompressionDictionaryLite() = 0;
/**
* @brief Get the number of code/value mappings in this dictionary.
*
* @return The number of codes/values in this dictionary.
**/
inline std::uint32_t numberOfCodes() const {
return number_of_codes_including_null_;
}
/**
* @brief Get the minimum number of bits needed to represent a code for this
* dictionary.
*
* @return The length of codes for this dictionary in bits.
**/
inline std::uint8_t codeLengthBits() const {
return code_length_bits_;
}
/**
* @brief Determine whether this dictionary contains a code for NULL values.
*
* @return Whether this dictionary contains NULL.
**/
inline bool containsNull() const {
return getNullCode() != std::numeric_limits<std::uint32_t>::max();
}
/**
* @brief Get the code representing NULL in this dictionary, or the maximum
* possible value of a std::uint32_t if NULL is not present in this
* dictionary.
*
* @return The code representing NULL in this dictionary, or UINT32_MAX if
* NULL is not present in this dictionary.
**/
inline std::uint32_t getNullCode() const {
return *(static_cast<const std::uint32_t*>(dictionary_memory_) + 1);
}
/**
* @brief Get an untyped pointer to the value represented by the specified
* code.
* @note This version is for codes of 8 bits or less. Also see
* getUntypedValueForShortCode() and getUntypedValueForCode().
* @warning It is an error to use this method with a code which does not
* exist in this dictionary, i.e. code must be less than
* numberOfCodes().
*
* @param code The compressed code to get the value for.
* @return An untyped pointer to the value that corresponds to code.
**/
template <bool check_null = true>
inline const void* getUntypedValueForByteCode(const std::uint8_t code) const {
if (type_is_variable_length_) {
return variableLengthGetUntypedValueHelper<std::uint8_t, check_null>(code);
} else {
return fixedLengthGetUntypedValueHelper<std::uint8_t, check_null>(code);
}
}
/**
* @brief Get an untyped pointer to the value represented by the specified
* code.
* @note This version is for codes of 16 bits or less. Also see
* getUntypedValueForByteCode() and getUntypedValueForCode().
* @warning It is an error to use this method with a code which does not
* exist in this dictionary, i.e. code must be less than
* numberOfCodes().
*
* @param code The compressed code to get the value for.
* @return An untyped pointer to the value that corresponds to code.
**/
template <bool check_null = true>
inline const void* getUntypedValueForShortCode(const std::uint16_t code) const {
if (type_is_variable_length_) {
return variableLengthGetUntypedValueHelper<std::uint16_t, check_null>(code);
} else {
return fixedLengthGetUntypedValueHelper<std::uint16_t, check_null>(code);
}
}
/**
* @brief Get an untyped pointer to the value represented by the specified
* code.
* @note This version is for any code up to the maximum length of 32 bits.
* Also see getUntypedValueForByteCode() and
* getUntypedValueForShortCode().
* @warning It is an error to use this method with a code which does not
* exist in this dictionary, i.e. code must be less than
* numberOfCodes().
*
* @param code The compressed code to get the value for.
* @return An untyped pointer to the value that corresponds to code.
**/
template <bool check_null = true>
inline const void* getUntypedValueForCode(const std::uint32_t code) const {
if (type_is_variable_length_) {
return variableLengthGetUntypedValueHelper<std::uint32_t, check_null>(code);
} else {
return fixedLengthGetUntypedValueHelper<std::uint32_t, check_null>(code);
}
}
/**
* @brief Get the value represented by the specified code as a TypedValue.
* @note This version is for codes of 8 bits or less. Also see
* getTypedValueForShortCode() and getTypedValueForCode().
* @warning It is an error to use this method with a code which does not
* exist in this dictionary, i.e. code must be less than
* numberOfCodes().
*
* @param code The compressed code to get the value for.
* @return The typed value that corresponds to code.
**/
inline TypedValue getTypedValueForByteCode(const std::uint8_t code) const {
if (type_is_variable_length_) {
return variableLengthGetTypedValueHelper<std::uint8_t>(code);
} else {
return fixedLengthGetTypedValueHelper<std::uint8_t>(code);
}
}
/**
* @brief Get the value represented by the specified code as a TypedValue.
* @note This version is for codes of 16 bits or less. Also see
* getTypedValueForByteCode() and getTypedValueForCode().
* @warning It is an error to use this method with a code which does not
* exist in this dictionary, i.e. code must be less than
* numberOfCodes().
*
* @param code The compressed code to get the value for.
* @return The typed value that corresponds to code.
**/
inline TypedValue getTypedValueForShortCode(const std::uint16_t code) const {
if (type_is_variable_length_) {
return variableLengthGetTypedValueHelper<std::uint16_t>(code);
} else {
return fixedLengthGetTypedValueHelper<std::uint16_t>(code);
}
}
/**
* @brief Get the value represented by the specified code as a TypedValue.
* @note This version is for any code up to the maximum length of 32 bits.
* Also see getTypedValueForByteCode() and getTypedValueForShortCode().
* @warning It is an error to use this method with a code which does not
* exist in this dictionary, i.e. code must be less than
* numberOfCodes().
*
* @param code The compressed code to get the value for.
* @return The typed value that corresponds to code.
**/
inline TypedValue getTypedValueForCode(const std::uint32_t code) const {
if (type_is_variable_length_) {
return variableLengthGetTypedValueHelper<std::uint32_t>(code);
} else {
return fixedLengthGetTypedValueHelper<std::uint32_t>(code);
}
}
protected:
template <typename CodeType, bool check_null = true>
inline const void* fixedLengthGetUntypedValueHelper(const CodeType code) const {
if (check_null && (code == getNullCode())) {
return nullptr;
}
DCHECK_LT(code, numberOfCodes());
return static_cast<const char*>(dictionary_memory_)
+ 2 * sizeof(std::uint32_t) // Header.
+ code * type_fixed_byte_length_; // Index into value array.
}
template <typename CodeType, bool check_null = true>
inline const void* variableLengthGetUntypedValueHelper(const CodeType code) const {
if (check_null && (code == getNullCode())) {
return nullptr;
}
DCHECK_LT(code, numberOfCodes());
const void *retval = variable_length_data_region_
+ static_cast<const std::uint32_t*>(dictionary_memory_)[code + 2];
DCHECK_LT(retval, static_cast<const char*>(dictionary_memory_) + dictionary_memory_size_);
return retval;
}
template <typename CodeType>
inline TypedValue fixedLengthGetTypedValueHelper(const CodeType code) const {
if (code == getNullCode()) {
return TypedValue(type_.getTypeID());;
}
DCHECK_LT(code, numberOfCodes());
return type_.makeValue(static_cast<const char*>(dictionary_memory_)
+ 2 * sizeof(std::uint32_t) // Header.
+ code * type_fixed_byte_length_, // Index into value array.
type_fixed_byte_length_);
}
template <typename CodeType>
inline TypedValue variableLengthGetTypedValueHelper(const CodeType code) const {
if (code == getNullCode()) {
return TypedValue(type_.getTypeID());
}
DCHECK_LT(code, numberOfCodes());
std::uint32_t value_offset = static_cast<const std::uint32_t*>(dictionary_memory_)[code + 2];
const void *data_ptr = variable_length_data_region_ + value_offset;
DCHECK_LT(data_ptr, static_cast<const char*>(dictionary_memory_) + dictionary_memory_size_);
std::size_t data_size = (code == *static_cast<const std::uint32_t*>(dictionary_memory_) - 1) ?
(static_cast<const char*>(dictionary_memory_)
+ dictionary_memory_size_
- static_cast<const char*>(data_ptr))
: (static_cast<const std::uint32_t*>(dictionary_memory_)[code + 3] - value_offset);
return TypedValue(type_.getTypeID(), data_ptr, data_size);
}
const Type &type_;
const bool type_is_variable_length_;
const void *dictionary_memory_;
const std::size_t dictionary_memory_size_;
std::uint32_t number_of_codes_including_null_;
std::uint8_t code_length_bits_;
const std::size_t type_fixed_byte_length_;
const char *variable_length_data_region_;
private:
bool paranoidOffsetsCheck() const;
DISALLOW_COPY_AND_ASSIGN(CompressionDictionaryLite);
};
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_COMPRESSION_COMPRESSION_DICTIONARY_LITE_HPP_