diff --git a/include/flatmemory/details/operator.hpp b/include/flatmemory/details/operator.hpp deleted file mode 100644 index dea56cb..0000000 --- a/include/flatmemory/details/operator.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2024 Dominik Drexler - * - * This program 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. - * - * This program 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 this program. If not, see . - */ - -#ifndef FLATMEMORY_OPERATOR_HPP_ -#define FLATMEMORY_OPERATOR_HPP_ - -namespace flatmemory -{ -/** - * Implementation class. - * - * Provide overload with your Tag. - * - * Define operations between Builder, View, ConstView - */ -template -class Operator -{ -}; -} - -#endif diff --git a/include/flatmemory/details/types/bitset.hpp b/include/flatmemory/details/types/bitset.hpp index 90877b9..00b21cf 100644 --- a/include/flatmemory/details/types/bitset.hpp +++ b/include/flatmemory/details/types/bitset.hpp @@ -71,30 +71,40 @@ class Layout> }; /** - * Operator + * BitsetUtils */ -template -class Operator> +class BitsetUtils { public: + template static constexpr std::size_t block_size = sizeof(Block) * 8; // 000... + template static constexpr Block block_zeroes = 0; // 111... + template static constexpr Block block_ones = Block(-1); // 100... - static constexpr Block block_msb_one = Block(1) << (block_size - 1); + template + static constexpr Block block_msb_one = Block(1) << (block_size - 1); // 011... - static constexpr Block block_msb_zero = block_ones & (~block_msb_one); + template + static constexpr Block block_msb_zero = block_ones&(~block_msb_one); // 111... static constexpr std::size_t no_position = std::size_t(-1); /** - * Helpers + * Operators */ - static int64_t find_last_relevant_block(const std::vector& blocks, bool default_bit_value); + template + requires HaveSameBlockType && HaveCompatibleTagType + static bool is_superseteq(const B1& lhs, const B2& rhs); + + template + requires HaveSameBlockType && HaveCompatibleTagType + static bool are_disjoint(const B1& lhs, const B2& rhs); /** * Lookup @@ -107,10 +117,14 @@ class Operator> template static size_t count(const B& bitset); + template + static int64_t find_last_relevant_block(const std::vector& blocks, bool default_bit_value); + /** * Iterators */ + template class const_iterator { private: @@ -149,10 +163,13 @@ class Operator> * Math */ + template static size_t get_lsb_position(Block n) noexcept; + template static size_t get_index(size_t position) noexcept; + template static size_t get_offset(size_t position) noexcept; }; @@ -177,14 +194,6 @@ bool operator!=(const B1& lhs, const B2& rhs); template Builder> operator~(const B& element); -template -requires HaveSameBlockType && HaveCompatibleTagType -bool is_superseteq(const B1& lhs, const B2& rhs); - -template -requires HaveSameBlockType && HaveCompatibleTagType -bool are_disjoint(const B1& lhs, const B2& rhs); - /** * Builder */ @@ -196,11 +205,10 @@ class Builder> : public IBuilder>> using BlockType = Block; using TagType = Tag; - using BitsetOperator = Operator>; using BitsetLayout = Layout>; using BitsetView = View>; using BitsetConstView = ConstView>; - using const_iterator = typename BitsetOperator::const_iterator; + using const_iterator = typename BitsetUtils::const_iterator; private: bool m_default_bit_value; @@ -291,6 +299,18 @@ class Builder> : public IBuilder>> template requires HasBlockType && HasCompatibleTagType Builder& operator-=(const Other& other); + /** + * Operators + */ + + template + requires HasBlockType && HasCompatibleTagType + bool is_superseteq(const B& other); + + template + requires HasBlockType && HasCompatibleTagType + bool are_disjoint(const B& other); + /** * Lookup */ @@ -339,10 +359,9 @@ class View> using TagType = Tag; using BitsetLayout = Layout>; - using BitsetOperator = Operator>; using BitsetView = View>; using BitsetConstView = ConstView>; - using const_iterator = typename BitsetOperator::const_iterator; + using const_iterator = typename BitsetUtils::const_iterator; private: uint8_t* m_buf; @@ -358,6 +377,18 @@ class View> /// @param buf explicit View(uint8_t* buf); + /** + * Operators + */ + + template + requires HasBlockType && HasCompatibleTagType + bool is_superseteq(const B& other); + + template + requires HasBlockType && HasCompatibleTagType + bool are_disjoint(const B& other); + /** * Lookup */ @@ -402,10 +433,9 @@ class ConstView> using TagType = Tag; using BitsetLayout = Layout>; - using BitsetOperator = Operator>; using BitsetView = View>; using BitsetConstView = ConstView>; - using const_iterator = typename BitsetOperator::const_iterator; + using const_iterator = typename BitsetUtils::const_iterator; private: const uint8_t* m_buf; @@ -427,6 +457,18 @@ class ConstView> ConstView(const BitsetView& view); + /** + * Operators + */ + + template + requires HasBlockType && HasCompatibleTagType + bool is_superseteq(const B& other); + + template + requires HasBlockType && HasCompatibleTagType + bool are_disjoint(const B& other); + /** * Lookup */ @@ -482,30 +524,134 @@ constexpr void Layout>::print() const /* Operator */ -template -int64_t Operator>::find_last_relevant_block(const std::vector& blocks, bool default_bit_value) +template +requires HaveSameBlockType && HaveCompatibleTagType +bool BitsetUtils::is_superseteq(const B1& lhs, const B2& rhs) +{ + // Fetch data + const auto& blocks = lhs.get_blocks(); + bool default_bit_value = lhs.get_default_bit_value(); + const auto& other_blocks = rhs.get_blocks(); + bool other_default_bit_value = rhs.get_default_bit_value(); + + if (other_default_bit_value && !default_bit_value) + { + // blocks has finitely many and other blocks has infinitely many set bits. + // Hence blocks cannot be a superseteq of other_blocks. + return false; + } + + std::size_t common_size = std::min(blocks.size(), other_blocks.size()); + + for (std::size_t index = 0; index < common_size; ++index) + { + if ((blocks[index] & other_blocks[index]) != other_blocks[index]) + { + // There exists a set bit in other block that is not set in block. + return false; + } + } + + if (other_blocks.size() <= blocks.size()) + { + // blocks can only contain additional set bits + return true; + } + + if (default_bit_value) + { + return true; + } + + for (std::size_t index = common_size; index < other_blocks.size(); ++index) + { + if (other_blocks[index]) + { + // other_block contains additional set bits + return false; + } + } + + return true; +} + +template +requires HaveSameBlockType && HaveCompatibleTagType +bool BitsetUtils::are_disjoint(const B1& lhs, const B2& rhs) +{ + // Fetch data + const auto& blocks = lhs.get_blocks(); + bool default_bit_value = lhs.get_default_bit_value(); + const auto& other_blocks = rhs.get_blocks(); + bool other_default_bit_value = rhs.get_default_bit_value(); + + if (default_bit_value && other_default_bit_value) + { + // blocks and other blocks have infinitely many set bits after finite sized explicit bitsets. + // Hence blocks and other_blocks cannot be disjoint. + return false; + } + + std::size_t common_size = std::min(blocks.size(), other_blocks.size()); + + for (std::size_t index = 0; index < common_size; ++index) + { + if ((blocks[index] & other_blocks[index]) > 0) + { + // block and other_block have set bits in common + return false; + } + } + + if (default_bit_value && !other_default_bit_value) + { + for (std::size_t index = common_size; index < other_blocks.size(); ++index) + { + if (other_blocks[index] > 0) + { + // other_blocks has a set bit in common with blocks in the infinite part. + return false; + } + } + } + + if (!default_bit_value && other_default_bit_value) + { + for (std::size_t index = common_size; index < blocks.size(); ++index) + { + if (blocks[index] > 0) + { + // blocks has a set bit in common with other_blocks in the infinite part. + return false; + } + } + } + + return true; +} + +template +int64_t BitsetUtils::find_last_relevant_block(const std::vector& blocks, bool default_bit_value) { int64_t last_relevant_block_index = static_cast(blocks.size()) - 1; - for (; (last_relevant_block_index >= 0) - && (blocks[last_relevant_block_index] == (default_bit_value ? Layout>::block_ones : Layout>::block_zeroes)); + for (; (last_relevant_block_index >= 0) && (blocks[last_relevant_block_index] == (default_bit_value ? block_ones : block_zeroes) ); --last_relevant_block_index) { } return last_relevant_block_index; } -template template -bool Operator>::get(const B& bitset, std::size_t position) +bool BitsetUtils::get(const B& bitset, std::size_t position) { { - const std::size_t index = get_index(position); + const std::size_t index = get_index(position); const auto& blocks = bitset.get_blocks(); if (index < blocks.size()) { - const std::size_t offset = get_offset(position); - return (blocks[index] & (static_cast(1) << offset)) != 0; + const std::size_t offset = get_offset(position); + return (blocks[index] & (static_cast(1) << offset)) != 0; } else { @@ -514,9 +660,8 @@ bool Operator>::get(const B& bitset, std::size_t position) } } -template template -size_t Operator>::count(const B& bitset) +size_t BitsetUtils::count(const B& bitset) { auto count = (size_t) 0; for (auto it = bitset.begin(); it != bitset.end(); ++it) @@ -526,8 +671,8 @@ size_t Operator>::count(const B& bitset) return count; } -template -void Operator>::const_iterator::next_set_bit() +template +void BitsetUtils::const_iterator::next_set_bit() { assert(m_pos != m_end_pos); do @@ -535,13 +680,13 @@ void Operator>::const_iterator::next_set_bit() // Advance position ++m_pos; ++m_bit_index; - if (m_bit_index == block_size) + if (m_bit_index == block_size) { ++m_block_index; if (m_block_index == m_num_blocks) { // Reached end of blocks, set m_pos to end - m_pos += block_size - 1; + m_pos += block_size - 1; break; } m_bit_index = 0; @@ -551,7 +696,7 @@ void Operator>::const_iterator::next_set_bit() if (m_cur_block) { // If there are set bits in the current value - const auto lsb_position = get_lsb_position(m_cur_block); + const auto lsb_position = get_lsb_position(m_cur_block); m_bit_index += lsb_position; m_pos += lsb_position; // shift by + 1 to advance further @@ -561,28 +706,28 @@ void Operator>::const_iterator::next_set_bit() else { // Skip the remaining bits, point to last position in the current block - m_pos += block_size - m_bit_index - 1; + m_pos += block_size - m_bit_index - 1; ++m_block_index; m_bit_index = -1; // Fetch next data block or zeroes - m_cur_block = m_block_index < m_num_blocks ? m_blocks[m_block_index] : block_zeroes; + m_cur_block = m_block_index < m_num_blocks ? m_blocks[m_block_index] : block_zeroes; } } while (m_pos < m_end_pos); } -template -Operator>::const_iterator::const_iterator() : m_blocks(nullptr), m_num_blocks(0), m_block_index(0), m_bit_index(-1) +template +BitsetUtils::const_iterator::const_iterator() : m_blocks(nullptr), m_num_blocks(0), m_block_index(0), m_bit_index(-1) { } -template -Operator>::const_iterator::const_iterator(bool default_bit_value, const Block* blocks, size_t num_blocks, bool begin) : +template +BitsetUtils::const_iterator::const_iterator(bool default_bit_value, const Block* blocks, size_t num_blocks, bool begin) : m_blocks(blocks), m_num_blocks(num_blocks), m_block_index(0), m_bit_index(-1), - m_cur_block(num_blocks > 0 ? m_blocks[m_block_index] : block_zeroes), - m_end_pos((m_num_blocks + 1) * block_size - 1), + m_cur_block(num_blocks > 0 ? m_blocks[m_block_index] : block_zeroes), + m_end_pos((m_num_blocks + 1) * block_size - 1), m_pos(begin ? -1 : m_end_pos) { if (default_bit_value) @@ -607,59 +752,59 @@ Operator>::const_iterator::const_iterator(bool default_bit_va } } -template -size_t Operator>::const_iterator::operator*() const +template +size_t BitsetUtils::const_iterator::const_iterator::operator*() const { // Do not allow interpreting end as position. assert(m_pos < m_end_pos); return m_pos; } -template -Operator>::const_iterator& Operator>::const_iterator::operator++() +template +BitsetUtils::const_iterator& BitsetUtils::const_iterator::operator++() { next_set_bit(); return *this; } -template -Operator>::const_iterator Operator>::const_iterator::operator++(int) +template +BitsetUtils::const_iterator BitsetUtils::const_iterator::operator++(int) { const_iterator tmp = *this; ++(*this); return tmp; } -template -bool Operator>::const_iterator::operator==(const const_iterator& other) const +template +bool BitsetUtils::const_iterator::const_iterator::operator==(const const_iterator& other) const { return m_pos == other.m_pos; } -template -bool Operator>::const_iterator::operator!=(const const_iterator& other) const +template +bool BitsetUtils::const_iterator::const_iterator::operator!=(const const_iterator& other) const { return !(*this == other); } -template -size_t Operator>::get_lsb_position(Block n) noexcept +template +size_t BitsetUtils::get_lsb_position(Block n) noexcept { assert(n != 0); const Block v = n & (-n); return std::bit_width(v) - 1; // bit_width uses more efficient specialized cpu instructions } -template -size_t Operator>::get_index(size_t position) noexcept +template +size_t BitsetUtils::get_index(size_t position) noexcept { - return position / block_size; + return position / block_size; } -template -size_t Operator>::get_offset(size_t position) noexcept +template +size_t BitsetUtils::get_offset(size_t position) noexcept { - return position % block_size; + return position % block_size; } /* Builder */ @@ -710,7 +855,7 @@ void Builder>::resize_to_fit(const Other& other) { if (m_blocks.size() < other.get_blocks().size()) { - m_blocks.resize(other.get_blocks().size(), m_default_bit_value ? BitsetOperator::block_ones : BitsetOperator::block_zeroes); + m_blocks.resize(other.get_blocks().size(), m_default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes); } assert(m_blocks.size() > 0); @@ -738,14 +883,14 @@ Builder>::Builder() : Builder(0) template Builder>::Builder(std::size_t size) : m_default_bit_value(false), - m_blocks((size / BitsetOperator::block_size) + 1, BitsetOperator::block_zeroes) + m_blocks((size / BitsetUtils::block_size) +1, BitsetUtils::block_zeroes) { } template Builder>::Builder(std::size_t size, bool default_bit_value) : m_default_bit_value(default_bit_value), - m_blocks((size / BitsetOperator::block_size) + 1, default_bit_value ? BitsetOperator::block_ones : BitsetOperator::block_zeroes) + m_blocks((size / BitsetUtils::block_size) +1, default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes) { } @@ -780,7 +925,7 @@ void Builder>::shrink_to_fit() { int32_t last_non_default_block_index = m_blocks.size() - 1; - const Block default_block = m_default_bit_value ? BitsetOperator::block_ones : BitsetOperator::block_zeroes; + const Block default_block = m_default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes; for (; last_non_default_block_index >= 0; --last_non_default_block_index) { @@ -796,12 +941,12 @@ void Builder>::shrink_to_fit() template void Builder>::set(std::size_t position) { - const std::size_t index = BitsetOperator::get_index(position); - const std::size_t offset = BitsetOperator::get_offset(position); + const std::size_t index = BitsetUtils::get_index(position); + const std::size_t offset = BitsetUtils::get_offset(position); if (index >= m_blocks.size()) { - m_blocks.resize(index + 1, m_default_bit_value ? BitsetOperator::block_ones : BitsetOperator::block_zeroes); + m_blocks.resize(index + 1, m_default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes); } m_blocks[index] |= (static_cast(1) << offset); // Set the bit at the offset @@ -810,12 +955,12 @@ void Builder>::set(std::size_t position) template void Builder>::unset(std::size_t position) { - const std::size_t index = BitsetOperator::get_index(position); - const std::size_t offset = BitsetOperator::get_offset(position); + const std::size_t index = BitsetUtils::get_index(position); + const std::size_t offset = BitsetUtils::get_offset(position); if (index >= m_blocks.size()) { - m_blocks.resize(index + 1, m_default_bit_value ? BitsetOperator::block_ones : BitsetOperator::block_zeroes); + m_blocks.resize(index + 1, m_default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes); } m_blocks[index] &= ~(static_cast(1) << offset); // Set the bit at the offset @@ -826,7 +971,7 @@ void Builder>::unset_all() { assert(m_blocks.size() > 0); - m_blocks[0] = (m_default_bit_value) ? BitsetOperator::block_ones : BitsetOperator::block_zeroes; + m_blocks[0] = (m_default_bit_value) ? BitsetUtils::block_ones : BitsetUtils::block_zeroes; m_blocks.resize(1); } @@ -968,14 +1113,24 @@ requires HasBlockType && HasCompatibleTagType Builder< return *this; } +template +template +requires HasBlockType && HasCompatibleTagType +bool Builder>::is_superseteq(const B& other) { return BitsetUtils::is_superseteq(*this, other); } + +template +template +requires HasBlockType && HasCompatibleTagType +bool Builder>::are_disjoint(const B& other) { return BitsetUtils::are_disjoint(*this, other); } + template bool Builder>::get(std::size_t position) const { - const std::size_t index = BitsetOperator::get_index(position); + const std::size_t index = BitsetUtils::get_index(position); if (index < m_blocks.size()) { - const std::size_t offset = BitsetOperator::get_offset(position); + const std::size_t offset = BitsetUtils::get_offset(position); return (m_blocks[index] & (static_cast(1) << offset)) != 0; } else @@ -987,14 +1142,14 @@ bool Builder>::get(std::size_t position) const template size_t Builder>::count() const { - return BitsetOperator::count(*this); + return BitsetUtils::count(*this); } template std::size_t Builder>::next_set_bit(std::size_t position) const { - std::size_t index = BitsetOperator::get_index(position); - std::size_t offset = BitsetOperator::get_offset(position); + std::size_t index = BitsetUtils::get_index(position); + std::size_t offset = BitsetUtils::get_offset(position); for (auto iter = m_blocks.begin() + index; iter < m_blocks.end(); ++iter) { @@ -1004,15 +1159,15 @@ std::size_t Builder>::next_set_bit(std::size_t position) cons if (value) { // If there are set bits in the current value - const auto lsb_position = BitsetOperator::get_lsb_position(value); - return index * BitsetOperator::block_size + offset + lsb_position; + const auto lsb_position = BitsetUtils::get_lsb_position(value); + return index * BitsetUtils::block_size + offset + lsb_position; } // Reset offset for the next value offset = 0; } - return BitsetOperator::no_position; + return BitsetUtils::no_position; } template @@ -1059,18 +1214,28 @@ View>::View(uint8_t* buf) : m_buf(buf) assert(m_buf); } +template +template +requires HasBlockType && HasCompatibleTagType +bool View>::is_superseteq(const B& other) { return BitsetUtils::is_superseteq(*this, other); } + +template +template +requires HasBlockType && HasCompatibleTagType +bool View>::are_disjoint(const B& other) { return BitsetUtils::are_disjoint(*this, other); } + template bool View>::get(std::size_t position) const { assert(m_buf); - return BitsetOperator::get(*this, position); + return BitsetUtils::get(*this, position); } template size_t View>::count() const { assert(m_buf); - return BitsetOperator::count(*this); + return BitsetUtils::count(*this); } template @@ -1160,18 +1325,28 @@ ConstView>::ConstView(const BitsetView& view) : m_buf(view.bu { } +template +template +requires HasBlockType && HasCompatibleTagType +bool ConstView>::is_superseteq(const B& other) { return BitsetUtils::is_superseteq(*this, other); } + +template +template +requires HasBlockType && HasCompatibleTagType +bool ConstView>::are_disjoint(const B& other) { return BitsetUtils::are_disjoint(*this, other); } + template bool ConstView>::get(std::size_t position) const { assert(m_buf); - return BitsetOperator::get(*this, position); + return BitsetUtils::get(*this, position); } template size_t ConstView>::count() const { assert(m_buf); - return BitsetOperator::count(*this); + return BitsetUtils::count(*this); } template @@ -1244,61 +1419,6 @@ ConstView> ConstView>::get_blocks() const /* Free function operators */ -template -requires HaveSameBlockType && HaveCompatibleTagType -bool are_disjoint(const B1& lhs, const B2& rhs) -{ - // Fetch data - const auto& blocks = lhs.get_blocks(); - bool default_bit_value = lhs.get_default_bit_value(); - const auto& other_blocks = rhs.get_blocks(); - bool other_default_bit_value = rhs.get_default_bit_value(); - - if (default_bit_value && other_default_bit_value) - { - // blocks and other blocks have infinitely many set bits after finite sized explicit bitsets. - // Hence blocks and other_blocks cannot be disjoint. - return false; - } - - std::size_t common_size = std::min(blocks.size(), other_blocks.size()); - - for (std::size_t index = 0; index < common_size; ++index) - { - if ((blocks[index] & other_blocks[index]) > 0) - { - // block and other_block have set bits in common - return false; - } - } - - if (default_bit_value && !other_default_bit_value) - { - for (std::size_t index = common_size; index < other_blocks.size(); ++index) - { - if (other_blocks[index] > 0) - { - // other_blocks has a set bit in common with blocks in the infinite part. - return false; - } - } - } - - if (!default_bit_value && other_default_bit_value) - { - for (std::size_t index = common_size; index < blocks.size(); ++index) - { - if (blocks[index] > 0) - { - // blocks has a set bit in common with other_blocks in the infinite part. - return false; - } - } - } - - return true; -} - template bool operator==(const B& lhs, const B& rhs) { @@ -1318,9 +1438,12 @@ bool operator==(const B& lhs, const B& rhs) for (std::size_t index = common_size; index < max_size; ++index) { - auto this_value = index < blocks.size() ? blocks[index] : (default_bit_value ? B::BitsetOperator::block_ones : B::BitsetOperator::block_zeroes); - auto other_value = - index < other_blocks.size() ? other_blocks[index] : (other_default_bit_value ? B::BitsetOperator::block_ones : B::BitsetOperator::block_zeroes); + auto this_value = index < blocks.size() ? + blocks[index] : + (default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes); + auto other_value = index < other_blocks.size() ? other_blocks[index] : + (other_default_bit_value ? BitsetUtils::block_ones : + BitsetUtils::block_zeroes); if (this_value != other_value) { @@ -1352,9 +1475,12 @@ bool operator==(const B1& lhs, const B2& rhs) for (std::size_t index = common_size; index < max_size; ++index) { - auto this_value = index < blocks.size() ? blocks[index] : (default_bit_value ? B1::BitsetOperator::block_ones : B1::BitsetOperator::block_zeroes); - auto other_value = - index < other_blocks.size() ? other_blocks[index] : (other_default_bit_value ? B1::BitsetOperator::block_ones : B1::BitsetOperator::block_zeroes); + auto this_value = index < blocks.size() ? + blocks[index] : + (default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes); + auto other_value = index < other_blocks.size() ? + other_blocks[index] : + (other_default_bit_value ? BitsetUtils::block_ones : BitsetUtils::block_zeroes); if (this_value != other_value) { @@ -1383,57 +1509,6 @@ Builder> operator~(const B& e return result; } -template -requires HaveSameBlockType && HaveCompatibleTagType -bool is_superseteq(const B1& lhs, const B2& rhs) -{ - // Fetch data - const auto& blocks = lhs.get_blocks(); - bool default_bit_value = lhs.get_default_bit_value(); - const auto& other_blocks = rhs.get_blocks(); - bool other_default_bit_value = rhs.get_default_bit_value(); - - if (other_default_bit_value && !default_bit_value) - { - // blocks has finitely many and other blocks has infinitely many set bits. - // Hence blocks cannot be a superseteq of other_blocks. - return false; - } - - std::size_t common_size = std::min(blocks.size(), other_blocks.size()); - - for (std::size_t index = 0; index < common_size; ++index) - { - if ((blocks[index] & other_blocks[index]) != other_blocks[index]) - { - // There exists a set bit in other block that is not set in block. - return false; - } - } - - if (other_blocks.size() <= blocks.size()) - { - // blocks can only contain additional set bits - return true; - } - - if (default_bit_value) - { - return true; - } - - for (std::size_t index = common_size; index < other_blocks.size(); ++index) - { - if (other_blocks[index]) - { - // other_block contains additional set bits - return false; - } - } - - return true; -} - /** * Static assertions */ @@ -1486,7 +1561,8 @@ struct std::hash const bool default_bit_value = bitset.get_default_bit_value(); const auto& blocks = bitset.get_blocks(); - const auto default_block = default_bit_value ? B::BitsetOperator::block_ones : B::BitsetOperator::block_zeroes; + const auto default_block = + default_bit_value ? flatmemory::BitsetUtils::block_ones : flatmemory::BitsetUtils::block_zeroes; const auto seed = static_cast(default_block); // Find the last block that differs from the default block diff --git a/include/flatmemory/details/types/declarations.hpp b/include/flatmemory/details/types/declarations.hpp index 254be2e..e608599 100644 --- a/include/flatmemory/details/types/declarations.hpp +++ b/include/flatmemory/details/types/declarations.hpp @@ -20,7 +20,6 @@ #include "flatmemory/details/builder.hpp" #include "flatmemory/details/concepts.hpp" -#include "flatmemory/details/operator.hpp" #include "flatmemory/details/view.hpp" #include "flatmemory/details/view_const.hpp" diff --git a/include/flatmemory/details/types/optional.hpp b/include/flatmemory/details/types/optional.hpp index 6adf8b5..a6a6ade 100644 --- a/include/flatmemory/details/types/optional.hpp +++ b/include/flatmemory/details/types/optional.hpp @@ -26,7 +26,6 @@ #include "flatmemory/details/concepts.hpp" #include "flatmemory/details/layout.hpp" #include "flatmemory/details/layout_utils.hpp" -#include "flatmemory/details/operator.hpp" #include "flatmemory/details/view.hpp" #include "flatmemory/details/view_const.hpp" diff --git a/include/flatmemory/details/types/tuple.hpp b/include/flatmemory/details/types/tuple.hpp index f78024d..923e5ee 100644 --- a/include/flatmemory/details/types/tuple.hpp +++ b/include/flatmemory/details/types/tuple.hpp @@ -308,7 +308,11 @@ static bool compare_tuples(std::index_sequence, const T1& lhs, const T2& template bool operator==(const T& lhs, const T& rhs) { - return compare_tuples(std::make_index_sequence> {}, lhs, rhs); + if (&lhs != &rhs) + { + return compare_tuples(std::make_index_sequence> {}, lhs, rhs); + } + return true; } template diff --git a/include/flatmemory/details/types/vector.hpp b/include/flatmemory/details/types/vector.hpp index 51e926f..87da366 100644 --- a/include/flatmemory/details/types/vector.hpp +++ b/include/flatmemory/details/types/vector.hpp @@ -292,11 +292,17 @@ class ConstView> ConstView(const uint8_t* buf); /** - * Conversion constructor + * Conversion constructors */ ConstView(const View>& view); + /** + * Conversion assigments + */ + + ConstView& operator=(const View>& view); + /** * Element access */ @@ -354,7 +360,7 @@ class ConstView> * Definitions */ -// Layout +/* Layout */ template constexpr void Layout>::print() const @@ -369,7 +375,57 @@ constexpr void Layout>::print() const << "final_alignment: " << final_alignment << std::endl; } -// Builder +/* Operators */ + +template +bool operator==(const V& lhs, const V& rhs) +{ + if (&lhs != &rhs) + { + if (lhs.size() != rhs.size()) + { + return false; + } + for (size_t i = 0; i < lhs.size(); ++i) + { + if (lhs[i] != rhs[i]) + { + return false; + } + } + } + return true; +} + +template +requires HaveSameValueType +bool operator==(const V1& lhs, const V2& rhs) +{ + if (lhs.size() != rhs.size()) + { + return false; + } + for (size_t i = 0; i < lhs.size(); ++i) + { + if (lhs[i] != rhs[i]) + { + return false; + } + } + return true; +} + +template +bool operator!=(const V& lhs, const V& rhs) +{ + return !(lhs == rhs); +} + +template +requires HaveSameValueType +bool operator!=(const V1& lhs, const V2& rhs) { return !(lhs == rhs); } + +/* Builder */ template void Builder>::finish_impl() @@ -557,7 +613,7 @@ void Builder>::clear() m_data.clear(); } -// View +/* View */ template View>::View(uint8_t* buf) : m_buf(buf) @@ -834,7 +890,7 @@ size_t View>::size() const return read_value(m_buf + Layout>::vector_size_position); } -// ConstView +/* ConstView */ template ConstView>::ConstView(const uint8_t* buf) : m_buf(buf) @@ -847,6 +903,13 @@ ConstView>::ConstView(const View>& view) : m_buf(view.buffer { } +template +ConstView>& ConstView>::operator=(const View>& view) +{ + m_buf = view.buffer(); + return *this; +} + template void ConstView>::range_check(size_t pos) const { @@ -998,58 +1061,6 @@ size_t ConstView>::size() const return read_value(m_buf + Layout>::vector_size_position); } -/** - * Operators - */ - -template -bool operator==(const V& lhs, const V& rhs) -{ - if (&lhs != &rhs) - { - if (lhs.size() != rhs.size()) - { - return false; - } - for (size_t i = 0; i < lhs.size(); ++i) - { - if (lhs[i] != rhs[i]) - { - return false; - } - } - } - return true; -} - -template -requires HaveSameValueType -bool operator==(const V1& lhs, const V2& rhs) -{ - if (lhs.size() != rhs.size()) - { - return false; - } - for (size_t i = 0; i < lhs.size(); ++i) - { - if (lhs[i] != rhs[i]) - { - return false; - } - } - return true; -} - -template -bool operator!=(const V& lhs, const V& rhs) -{ - return !(lhs == rhs); -} - -template -requires HaveSameValueType -bool operator!=(const V1& lhs, const V2& rhs) { return !(lhs == rhs); } - /** * Static assertions */ diff --git a/tests/unit/types/bitset.cpp b/tests/unit/types/bitset.cpp index 8150feb..aec9b21 100644 --- a/tests/unit/types/bitset.cpp +++ b/tests/unit/types/bitset.cpp @@ -243,11 +243,11 @@ TEST(FlatmemoryTests, TypesBitsetAreDisjointTest) auto bitset_2 = Builder>(); bitset_2.set(2); - EXPECT_TRUE(are_disjoint(bitset_1, bitset_2)); + EXPECT_TRUE(bitset_1.are_disjoint(bitset_2)); bitset_2.set(1); - EXPECT_FALSE(are_disjoint(bitset_1, bitset_2)); + EXPECT_FALSE(bitset_1.are_disjoint(bitset_2)); } TEST(FlatmemoryTests, TypesBitsetIsSupersetTest) @@ -258,11 +258,11 @@ TEST(FlatmemoryTests, TypesBitsetIsSupersetTest) auto bitset_2 = Builder>(); bitset_2.set(2); - EXPECT_FALSE(is_superseteq(bitset_2, bitset_1)); + EXPECT_FALSE(bitset_2.is_superseteq(bitset_1)); bitset_2.set(1); - EXPECT_TRUE(is_superseteq(bitset_2, bitset_1)); + EXPECT_TRUE(bitset_2.is_superseteq(bitset_1)); } /**