| // 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. | |
| #pragma once | |
| #include <array> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <type_traits> | |
| #include <vector> | |
| #include "common/compiler_util.h" | |
| namespace doris { | |
| template <typename T> | |
| struct BitSetContainerTraits { | |
| static constexpr size_t RANGE = 0; | |
| }; | |
| template <> | |
| struct BitSetContainerTraits<int8_t> { | |
| static constexpr size_t RANGE = 256; | |
| }; | |
| template <> | |
| struct BitSetContainerTraits<int16_t> { | |
| static constexpr size_t RANGE = 65536; | |
| }; | |
| template <typename T> | |
| class BitSetContainer { | |
| public: | |
| using Self = BitSetContainer; | |
| using ElementType = T; | |
| static_assert(std::is_same_v<T, int8_t> || std::is_same_v<T, int16_t>, | |
| "BitSetContainer only supports int8_t or int16_t"); | |
| static constexpr size_t RANGE = BitSetContainerTraits<T>::RANGE; | |
| class Iterator { | |
| public: | |
| explicit Iterator(const std::array<bool, RANGE>* data, size_t index) | |
| : _data(data), _index(index) { | |
| _find_next(); | |
| } | |
| Iterator& operator++() { | |
| ++_index; | |
| _find_next(); | |
| return *this; | |
| } | |
| Iterator operator++(int) { | |
| Iterator ret_val = *this; | |
| ++(*this); | |
| return ret_val; | |
| } | |
| bool operator==(Iterator other) const { return _index == other._index; } | |
| bool operator!=(Iterator other) const { return !(*this == other); } | |
| T operator*() const { return static_cast<T>(_index); } | |
| T* operator->() const { | |
| _cached_value = static_cast<T>(_index); | |
| return &_cached_value; | |
| } | |
| using iterator_category = std::forward_iterator_tag; | |
| using difference_type = std::ptrdiff_t; | |
| using value_type = T; | |
| using pointer = const T*; | |
| using reference = const T&; | |
| private: | |
| void _find_next() { | |
| while (_index < RANGE && !(*_data)[_index]) { | |
| ++_index; | |
| } | |
| } | |
| const std::array<bool, RANGE>* _data; | |
| size_t _index; | |
| mutable T _cached_value = T(); | |
| }; | |
| BitSetContainer() { _data.fill(false); } | |
| ~BitSetContainer() = default; | |
| ALWAYS_INLINE void insert(const T& value) { | |
| auto idx = _to_index(value); | |
| if (!_data[idx]) { | |
| _data[idx] = true; | |
| _size++; | |
| } | |
| } | |
| ALWAYS_INLINE bool find(const T& value) const { return _data[_to_index(value)]; } | |
| void clear() { | |
| _data.fill(false); | |
| _size = 0; | |
| } | |
| size_t size() const { return _size; } | |
| Iterator begin() const { return Iterator(&_data, 0); } | |
| Iterator end() const { return Iterator(&_data, RANGE); } | |
| template <typename ColumnData> | |
| void find_batch(const ColumnData& data, size_t rows, std::vector<bool>& results) const { | |
| results.resize(rows); | |
| for (size_t i = 0; i < rows; ++i) { | |
| results[i] = find(data[i]); | |
| } | |
| } | |
| template <typename ColumnData> | |
| void find_batch(const ColumnData& data, size_t rows, std::vector<uint8_t>& results) const { | |
| results.resize(rows); | |
| for (size_t i = 0; i < rows; ++i) { | |
| results[i] = find(data[i]) ? 1 : 0; | |
| } | |
| } | |
| private: | |
| ALWAYS_INLINE constexpr size_t _to_index(T value) const { | |
| if constexpr (std::is_same_v<T, int8_t>) { | |
| return static_cast<uint8_t>(value); | |
| } else { | |
| return static_cast<uint16_t>(value); | |
| } | |
| } | |
| std::array<bool, RANGE> _data; | |
| size_t _size = 0; | |
| }; | |
| } // namespace doris |