Make packed bool vector datafiles match in-memory layout for vector_view.

This commit is contained in:
Daniel Patterson 2018-10-21 21:18:11 -07:00 committed by Daniel Paz-Soldan
parent 49e09294bf
commit cb5d596a5a
2 changed files with 27 additions and 7 deletions

View File

@ -30,22 +30,29 @@ namespace serialization
namespace detail
{
template <typename T, typename BlockT = unsigned char>
inline BlockT packBits(const T &data, std::size_t index, std::size_t count)
inline BlockT packBits(const T &data, std::size_t base_index, const std::size_t count)
{
static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool");
// Note: if this packing is changed, be sure to update vector_view<bool>
// as well, so that on-disk and in-memory layouts match.
BlockT value = 0;
for (std::size_t bit = 0; bit < count; ++bit, ++index)
value = (value << 1) | data[index];
for (std::size_t bit = 0; bit < count; ++bit)
{
value |= (data[base_index + bit] ? BlockT{1} : BlockT{0}) << bit;
}
return value;
}
template <typename T, typename BlockT = unsigned char>
inline void unpackBits(T &data, std::size_t index, std::size_t count, BlockT value)
inline void
unpackBits(T &data, const std::size_t base_index, const std::size_t count, const BlockT value)
{
static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool");
const BlockT mask = BlockT{1} << (count - 1);
for (std::size_t bit = 0; bit < count; value <<= 1, ++bit, ++index)
data[index] = value & mask;
for (std::size_t bit = 0; bit < count; ++bit)
{
data[base_index + bit] = value & (BlockT{1} << bit);
}
}
template <typename VectorT>

View File

@ -195,6 +195,8 @@ template <> class vector_view<bool>
{
BOOST_ASSERT_MSG(index < m_size, "invalid size");
const std::size_t bucket = index / WORD_BITS;
// Note: ordering of bits here should match packBits in storage/serialization.hpp
// so that directly mmap-ing data is possible
const auto offset = index % WORD_BITS;
return m_ptr[bucket] & (static_cast<Word>(1) << offset);
}
@ -224,11 +226,22 @@ template <> class vector_view<bool>
{
BOOST_ASSERT(index < m_size);
const auto bucket = index / WORD_BITS;
// Note: ordering of bits here should match packBits in storage/serialization.hpp
// so that directly mmap-ing data is possible
const auto offset = index % WORD_BITS;
return reference{m_ptr + bucket, static_cast<Word>(1) << offset};
}
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
friend std::ostream &operator<<(std::ostream &os, const vector_view<bool> &rhs)
{
for (std::size_t i = 0; i < rhs.size(); ++i)
{
os << (i > 0 ? " " : "") << rhs.at(i);
}
return os;
}
};
// Both vector_view<T> and the vector_view<bool> specializations share this impl.