1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef LIBPANDABASE_UTILS_BIT_TABLE_H
17b1994897Sopenharmony_ci#define LIBPANDABASE_UTILS_BIT_TABLE_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include "utils/arena_containers.h"
20b1994897Sopenharmony_ci#include "utils/bit_memory_region.h"
21b1994897Sopenharmony_ci#include "utils/bit_memory_stream.h"
22b1994897Sopenharmony_ci#include "utils/bit_vector.h"
23b1994897Sopenharmony_ci#include "utils/hash.h"
24b1994897Sopenharmony_ci#include <iomanip>
25b1994897Sopenharmony_ci#include "securec.h"
26b1994897Sopenharmony_ci
27b1994897Sopenharmony_cinamespace panda {
28b1994897Sopenharmony_ci
29b1994897Sopenharmony_ciclass VarintPack {
30b1994897Sopenharmony_cipublic:
31b1994897Sopenharmony_ci    static constexpr size_t INLINE_BITS = 4;
32b1994897Sopenharmony_ci    static constexpr size_t INLINE_MAX = 11;
33b1994897Sopenharmony_ci
34b1994897Sopenharmony_ci    template <size_t N>
35b1994897Sopenharmony_ci    static std::array<uint32_t, N> Read(BitMemoryStreamIn *stream)
36b1994897Sopenharmony_ci    {
37b1994897Sopenharmony_ci        static_assert(sizeof(uint64_t) * BITS_PER_BYTE >= N * INLINE_BITS);
38b1994897Sopenharmony_ci        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
39b1994897Sopenharmony_ci        std::array<uint32_t, N> values;
40b1994897Sopenharmony_ci        auto data = stream->Read<uint64_t>(N * INLINE_BITS);
41b1994897Sopenharmony_ci        for (size_t i = 0; i < N; i++) {
42b1994897Sopenharmony_ci            values[i] = ExtractBits(data, i * INLINE_BITS, INLINE_BITS);
43b1994897Sopenharmony_ci        }
44b1994897Sopenharmony_ci        for (size_t i = 0; i < N; i++) {
45b1994897Sopenharmony_ci            if (UNLIKELY(values[i] > INLINE_MAX)) {
46b1994897Sopenharmony_ci                values[i] = stream->Read<uint32_t>((values[i] - INLINE_MAX) * BITS_PER_BYTE);
47b1994897Sopenharmony_ci            }
48b1994897Sopenharmony_ci        }
49b1994897Sopenharmony_ci        return values;
50b1994897Sopenharmony_ci    }
51b1994897Sopenharmony_ci
52b1994897Sopenharmony_ci    template <size_t N, typename Container>
53b1994897Sopenharmony_ci    static void Write(BitMemoryStreamOut<Container> &stream, const std::array<uint32_t, N> &data)
54b1994897Sopenharmony_ci    {
55b1994897Sopenharmony_ci        for (auto value : data) {
56b1994897Sopenharmony_ci            if (value > INLINE_MAX) {
57b1994897Sopenharmony_ci                stream.Write(INLINE_MAX + BitsToBytesRoundUp(MinimumBitsToStore(value)), INLINE_BITS);
58b1994897Sopenharmony_ci            } else {
59b1994897Sopenharmony_ci                stream.Write(value, INLINE_BITS);
60b1994897Sopenharmony_ci            }
61b1994897Sopenharmony_ci        }
62b1994897Sopenharmony_ci        for (auto value : data) {
63b1994897Sopenharmony_ci            if (value > INLINE_MAX) {
64b1994897Sopenharmony_ci                stream.Write(value, BitsToBytesRoundUp(MinimumBitsToStore(value)) * BITS_PER_BYTE);
65b1994897Sopenharmony_ci            }
66b1994897Sopenharmony_ci        }
67b1994897Sopenharmony_ci    }
68b1994897Sopenharmony_ci};
69b1994897Sopenharmony_ci
70b1994897Sopenharmony_citemplate <typename>
71b1994897Sopenharmony_ciclass BitTable;
72b1994897Sopenharmony_ci
73b1994897Sopenharmony_citemplate <size_t NumColumns, typename Accessor, bool reverse_iteration = false>
74b1994897Sopenharmony_ciclass BitTableRow : public std::iterator<std::random_access_iterator_tag, Accessor, int32_t, Accessor *, Accessor &> {
75b1994897Sopenharmony_ci    using BitTableType = BitTable<Accessor>;
76b1994897Sopenharmony_ci
77b1994897Sopenharmony_cipublic:
78b1994897Sopenharmony_ci    static constexpr size_t NUM_COLUMNS = NumColumns;
79b1994897Sopenharmony_ci    static constexpr uint32_t NO_VALUE = BitTableType::NO_VALUE;
80b1994897Sopenharmony_ci
81b1994897Sopenharmony_ci    using Reversed = BitTableRow<NumColumns, Accessor, !reverse_iteration>;
82b1994897Sopenharmony_ci
83b1994897Sopenharmony_ci    BitTableRow() = default;
84b1994897Sopenharmony_ci    BitTableRow(const BitTableType *table, int row_index) : table_(table), row_index_(row_index) {}
85b1994897Sopenharmony_ci    explicit BitTableRow(Reversed *rhs) : table_(rhs->table_), row_index_(rhs->row_index_) {}
86b1994897Sopenharmony_ci
87b1994897Sopenharmony_ci    uint32_t GetRow() const
88b1994897Sopenharmony_ci    {
89b1994897Sopenharmony_ci        return row_index_;
90b1994897Sopenharmony_ci    }
91b1994897Sopenharmony_ci
92b1994897Sopenharmony_ci    std::string GetColumnStr(size_t column) const
93b1994897Sopenharmony_ci    {
94b1994897Sopenharmony_ci        if (Get(column) == NO_VALUE) {
95b1994897Sopenharmony_ci            return "-";
96b1994897Sopenharmony_ci        }
97b1994897Sopenharmony_ci        return std::to_string(Get(column));
98b1994897Sopenharmony_ci    }
99b1994897Sopenharmony_ci
100b1994897Sopenharmony_ci    Accessor GetAccessor()
101b1994897Sopenharmony_ci    {
102b1994897Sopenharmony_ci        return Accessor(this);
103b1994897Sopenharmony_ci    }
104b1994897Sopenharmony_ci
105b1994897Sopenharmony_ci    uint32_t Get(size_t index) const
106b1994897Sopenharmony_ci    {
107b1994897Sopenharmony_ci        return table_->ReadColumn(row_index_, index);
108b1994897Sopenharmony_ci    }
109b1994897Sopenharmony_ci
110b1994897Sopenharmony_ci    bool Has(size_t index) const
111b1994897Sopenharmony_ci    {
112b1994897Sopenharmony_ci        return Get(index) != BitTableType::NO_VALUE;
113b1994897Sopenharmony_ci    }
114b1994897Sopenharmony_ci
115b1994897Sopenharmony_ci    size_t ColumnsCount() const
116b1994897Sopenharmony_ci    {
117b1994897Sopenharmony_ci        return table_->GetColumnsCount();
118b1994897Sopenharmony_ci    }
119b1994897Sopenharmony_ci
120b1994897Sopenharmony_ci    bool IsValid() const
121b1994897Sopenharmony_ci    {
122b1994897Sopenharmony_ci        return row_index_ != -1;
123b1994897Sopenharmony_ci    }
124b1994897Sopenharmony_ci
125b1994897Sopenharmony_ci    bool operator==(const BitTableRow &rhs) const
126b1994897Sopenharmony_ci    {
127b1994897Sopenharmony_ci        return table_ == rhs.table_ && row_index_ == rhs.row_index_;
128b1994897Sopenharmony_ci    }
129b1994897Sopenharmony_ci
130b1994897Sopenharmony_ci    bool operator!=(const BitTableRow &rhs) const
131b1994897Sopenharmony_ci    {
132b1994897Sopenharmony_ci        return !(operator==(rhs));
133b1994897Sopenharmony_ci    }
134b1994897Sopenharmony_ci
135b1994897Sopenharmony_ci    ~BitTableRow() = default;
136b1994897Sopenharmony_ci
137b1994897Sopenharmony_ci    DEFAULT_COPY_SEMANTIC(BitTableRow);
138b1994897Sopenharmony_ci    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BitTableRow);
139b1994897Sopenharmony_ci
140b1994897Sopenharmony_ciprotected:
141b1994897Sopenharmony_ci    auto GetTable() const
142b1994897Sopenharmony_ci    {
143b1994897Sopenharmony_ci        return table_;
144b1994897Sopenharmony_ci    }
145b1994897Sopenharmony_ci
146b1994897Sopenharmony_ciprivate:
147b1994897Sopenharmony_ci    const BitTableType *table_ {nullptr};
148b1994897Sopenharmony_ci    int row_index_ {-1};
149b1994897Sopenharmony_ci
150b1994897Sopenharmony_ci    friend Reversed;
151b1994897Sopenharmony_ci    template <typename, bool>
152b1994897Sopenharmony_ci    friend class BitTableIterator;
153b1994897Sopenharmony_ci};
154b1994897Sopenharmony_ci
155b1994897Sopenharmony_citemplate <typename Accessor, bool reverse_iteration = false>
156b1994897Sopenharmony_ciclass BitTableIterator
157b1994897Sopenharmony_ci    : public std::iterator<std::random_access_iterator_tag, Accessor, int32_t, Accessor *, Accessor &> {
158b1994897Sopenharmony_cipublic:
159b1994897Sopenharmony_ci    BitTableIterator(const typename Accessor::BitTableType *table, int row_index) : row_(table, row_index) {}
160b1994897Sopenharmony_ci    explicit BitTableIterator(Accessor &row) : row_(row) {}
161b1994897Sopenharmony_ci
162b1994897Sopenharmony_ci    BitTableIterator &operator++()
163b1994897Sopenharmony_ci    {
164b1994897Sopenharmony_ci        if constexpr (reverse_iteration) {  // NOLINT
165b1994897Sopenharmony_ci            row_.row_index_--;
166b1994897Sopenharmony_ci        } else {  // NOLINT
167b1994897Sopenharmony_ci            row_.row_index_++;
168b1994897Sopenharmony_ci        }
169b1994897Sopenharmony_ci        return *this;
170b1994897Sopenharmony_ci    }
171b1994897Sopenharmony_ci
172b1994897Sopenharmony_ci    BitTableIterator &operator--()
173b1994897Sopenharmony_ci    {
174b1994897Sopenharmony_ci        if constexpr (reverse_iteration) {  // NOLINT
175b1994897Sopenharmony_ci            row_.row_index_++;
176b1994897Sopenharmony_ci        } else {  // NOLINT
177b1994897Sopenharmony_ci            row_.row_index_--;
178b1994897Sopenharmony_ci        }
179b1994897Sopenharmony_ci        return *this;
180b1994897Sopenharmony_ci    }
181b1994897Sopenharmony_ci
182b1994897Sopenharmony_ci    explicit operator bool() const
183b1994897Sopenharmony_ci    {
184b1994897Sopenharmony_ci        return row_.row_index_ >= 0 && helpers::ToUnsigned(row_.row_index_) < row_.table_->GetRowsCount();
185b1994897Sopenharmony_ci    }
186b1994897Sopenharmony_ci
187b1994897Sopenharmony_ci    bool operator==(const BitTableIterator &rhs) const
188b1994897Sopenharmony_ci    {
189b1994897Sopenharmony_ci        return row_ == rhs.row_;
190b1994897Sopenharmony_ci    }
191b1994897Sopenharmony_ci
192b1994897Sopenharmony_ci    bool operator!=(const BitTableIterator &rhs) const
193b1994897Sopenharmony_ci    {
194b1994897Sopenharmony_ci        return row_ != rhs.row_;
195b1994897Sopenharmony_ci    }
196b1994897Sopenharmony_ci
197b1994897Sopenharmony_ci    auto operator+(int32_t n) const
198b1994897Sopenharmony_ci    {
199b1994897Sopenharmony_ci        if constexpr (reverse_iteration) {  // NOLINT
200b1994897Sopenharmony_ci            return BitTableIterator(row_.table_, row_.row_index_ - n);
201b1994897Sopenharmony_ci        } else {  // NOLINT
202b1994897Sopenharmony_ci            return BitTableIterator(row_.table_, row_.row_index_ + n);
203b1994897Sopenharmony_ci        }
204b1994897Sopenharmony_ci    }
205b1994897Sopenharmony_ci    auto operator-(int32_t n) const
206b1994897Sopenharmony_ci    {
207b1994897Sopenharmony_ci        if constexpr (reverse_iteration) {  // NOLINT
208b1994897Sopenharmony_ci            return BitTableIterator(row_.table_, row_.row_index_ + n);
209b1994897Sopenharmony_ci        } else {  // NOLINT
210b1994897Sopenharmony_ci            return BitTableIterator(row_.table_, row_.row_index_ - n);
211b1994897Sopenharmony_ci        }
212b1994897Sopenharmony_ci    }
213b1994897Sopenharmony_ci    int32_t operator-(const BitTableIterator &rhs) const
214b1994897Sopenharmony_ci    {
215b1994897Sopenharmony_ci        if constexpr (reverse_iteration) {  // NOLINT
216b1994897Sopenharmony_ci            return rhs.row_.row_index_ - row_.row_index_;
217b1994897Sopenharmony_ci        } else {  // NOLINT
218b1994897Sopenharmony_ci            return row_.row_index_ - rhs.row_.row_index_;
219b1994897Sopenharmony_ci        }
220b1994897Sopenharmony_ci    }
221b1994897Sopenharmony_ci
222b1994897Sopenharmony_ci    auto &operator+=(int32_t n)
223b1994897Sopenharmony_ci    {
224b1994897Sopenharmony_ci        if constexpr (reverse_iteration) {  // NOLINT
225b1994897Sopenharmony_ci            row_.row_index_ -= n;
226b1994897Sopenharmony_ci        } else {  // NOLINT
227b1994897Sopenharmony_ci            row_.row_index_ += n;
228b1994897Sopenharmony_ci        }
229b1994897Sopenharmony_ci        return *this;
230b1994897Sopenharmony_ci    }
231b1994897Sopenharmony_ci
232b1994897Sopenharmony_ci    Accessor &operator*()
233b1994897Sopenharmony_ci    {
234b1994897Sopenharmony_ci        return row_;
235b1994897Sopenharmony_ci    }
236b1994897Sopenharmony_ci    Accessor *operator->()
237b1994897Sopenharmony_ci    {
238b1994897Sopenharmony_ci        return &row_;
239b1994897Sopenharmony_ci    }
240b1994897Sopenharmony_ci
241b1994897Sopenharmony_ci    ~BitTableIterator() = default;
242b1994897Sopenharmony_ci
243b1994897Sopenharmony_ci    DEFAULT_COPY_SEMANTIC(BitTableIterator);
244b1994897Sopenharmony_ci    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BitTableIterator);
245b1994897Sopenharmony_ci
246b1994897Sopenharmony_ciprivate:
247b1994897Sopenharmony_ci    Accessor row_;
248b1994897Sopenharmony_ci};
249b1994897Sopenharmony_ci
250b1994897Sopenharmony_citemplate <size_t NumColumns>
251b1994897Sopenharmony_cistruct BitTableDefault : public BitTableRow<NumColumns, BitTableDefault<NumColumns>> {
252b1994897Sopenharmony_ci    using Base = BitTableRow<NumColumns, BitTableDefault<NumColumns>>;
253b1994897Sopenharmony_ci    using Base::Base;
254b1994897Sopenharmony_ci};
255b1994897Sopenharmony_ci
256b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
257b1994897Sopenharmony_ci#define BIT_TABLE_HEADER(columns, name)            \
258b1994897Sopenharmony_ci    using Base = BitTableRow<columns, name>;       \
259b1994897Sopenharmony_ci    using BitTableRow<columns, name>::BitTableRow; \
260b1994897Sopenharmony_ci    template <int Column, int Dummy>               \
261b1994897Sopenharmony_ci    struct ColumnName;                             \
262b1994897Sopenharmony_ci    static constexpr const char *TABLE_NAME = #name;
263b1994897Sopenharmony_ci
264b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
265b1994897Sopenharmony_ci#define BIT_TABLE_COLUMN(index, name, upname)                                \
266b1994897Sopenharmony_ci    static constexpr size_t COLUMN_##upname = index;                         \
267b1994897Sopenharmony_ci    static constexpr const char COLUMN_NAME_##upname[] = #name; /* NOLINT */ \
268b1994897Sopenharmony_ci    template <int Dummy>                                                     \
269b1994897Sopenharmony_ci    struct ColumnName<index, Dummy> {                                        \
270b1994897Sopenharmony_ci        static constexpr const char VALUE[] = #name; /* NOLINT */            \
271b1994897Sopenharmony_ci    };                                                                       \
272b1994897Sopenharmony_ci    uint32_t Get##name() const                                               \
273b1994897Sopenharmony_ci    {                                                                        \
274b1994897Sopenharmony_ci        return Get(index);                                                   \
275b1994897Sopenharmony_ci    }                                                                        \
276b1994897Sopenharmony_ci    bool Has##name() const                                                   \
277b1994897Sopenharmony_ci    {                                                                        \
278b1994897Sopenharmony_ci        return Get(index) != NO_VALUE;                                       \
279b1994897Sopenharmony_ci    }
280b1994897Sopenharmony_ci
281b1994897Sopenharmony_citemplate <typename Accessor, size_t... Columns>
282b1994897Sopenharmony_ci// NOLINTNEXTLINE(readability-named-parameter)
283b1994897Sopenharmony_cistatic const char *const *GetBitTableColumnNamesImpl(std::index_sequence<Columns...>)
284b1994897Sopenharmony_ci{
285b1994897Sopenharmony_ci    static const std::array<const char *, sizeof...(Columns)> names = {
286b1994897Sopenharmony_ci        Accessor::template ColumnName<Columns, 0>::VALUE...};
287b1994897Sopenharmony_ci    return names.data();
288b1994897Sopenharmony_ci}
289b1994897Sopenharmony_ci
290b1994897Sopenharmony_citemplate <typename AccessorT>
291b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
292b1994897Sopenharmony_ciclass BitTable {
293b1994897Sopenharmony_cipublic:
294b1994897Sopenharmony_ci    static constexpr uint32_t NO_VALUE = -1;
295b1994897Sopenharmony_ci    static constexpr uint32_t NO_VALUE_DIFF = -1;
296b1994897Sopenharmony_ci
297b1994897Sopenharmony_ci    static constexpr size_t NUM_COLUMNS = AccessorT::NUM_COLUMNS;
298b1994897Sopenharmony_ci
299b1994897Sopenharmony_ci    using Accessor = AccessorT;
300b1994897Sopenharmony_ci    using RegionType = BitMemoryRegion<const uint8_t>;
301b1994897Sopenharmony_ci
302b1994897Sopenharmony_cipublic:
303b1994897Sopenharmony_ci    template <bool Reversed>
304b1994897Sopenharmony_ci    class Range {
305b1994897Sopenharmony_ci    public:
306b1994897Sopenharmony_ci        using RangeIterator =
307b1994897Sopenharmony_ci            std::conditional_t<Reversed, BitTableIterator<Accessor, true>, BitTableIterator<Accessor, false>>;
308b1994897Sopenharmony_ci
309b1994897Sopenharmony_ci        Range(BitTable *table, int start, int end) : table_(table), start_(start), end_(end) {}
310b1994897Sopenharmony_ci        auto begin()
311b1994897Sopenharmony_ci        {
312b1994897Sopenharmony_ci            return RangeIterator(table_, start_);
313b1994897Sopenharmony_ci        }
314b1994897Sopenharmony_ci        auto end()
315b1994897Sopenharmony_ci        {
316b1994897Sopenharmony_ci            return RangeIterator(table_, end_);
317b1994897Sopenharmony_ci        }
318b1994897Sopenharmony_ci        Accessor operator[](size_t index)
319b1994897Sopenharmony_ci        {
320b1994897Sopenharmony_ci            return *(RangeIterator(table_, start_) + index);
321b1994897Sopenharmony_ci        }
322b1994897Sopenharmony_ci
323b1994897Sopenharmony_ci    private:
324b1994897Sopenharmony_ci        BitTable *table_;
325b1994897Sopenharmony_ci        int start_;
326b1994897Sopenharmony_ci        int end_;
327b1994897Sopenharmony_ci    };
328b1994897Sopenharmony_ci
329b1994897Sopenharmony_ci    auto begin() const
330b1994897Sopenharmony_ci    {
331b1994897Sopenharmony_ci        return BitTableIterator<Accessor, false>(this, 0);
332b1994897Sopenharmony_ci    }
333b1994897Sopenharmony_ci
334b1994897Sopenharmony_ci    auto begin()
335b1994897Sopenharmony_ci    {
336b1994897Sopenharmony_ci        return BitTableIterator<Accessor, false>(this, 0);
337b1994897Sopenharmony_ci    }
338b1994897Sopenharmony_ci
339b1994897Sopenharmony_ci    auto end() const
340b1994897Sopenharmony_ci    {
341b1994897Sopenharmony_ci        return BitTableIterator<Accessor, false>(this, GetRowsCount());
342b1994897Sopenharmony_ci    }
343b1994897Sopenharmony_ci
344b1994897Sopenharmony_ci    auto end()
345b1994897Sopenharmony_ci    {
346b1994897Sopenharmony_ci        return BitTableIterator<Accessor, false>(this, GetRowsCount());
347b1994897Sopenharmony_ci    }
348b1994897Sopenharmony_ci
349b1994897Sopenharmony_ci    auto GetRange(int start, int end)
350b1994897Sopenharmony_ci    {
351b1994897Sopenharmony_ci        return Range<false>(this, start, end);
352b1994897Sopenharmony_ci    }
353b1994897Sopenharmony_ci    auto GetRangeReversed(int start, int end)
354b1994897Sopenharmony_ci    {
355b1994897Sopenharmony_ci        return Range<true>(this, end - 1, start - 1);
356b1994897Sopenharmony_ci    }
357b1994897Sopenharmony_ci    auto GetRangeReversed()
358b1994897Sopenharmony_ci    {
359b1994897Sopenharmony_ci        if (GetRowsCount() == 0) {
360b1994897Sopenharmony_ci            return Range<true>(this, -1, -1);
361b1994897Sopenharmony_ci        }
362b1994897Sopenharmony_ci        return Range<true>(this, GetRowsCount() - 1, -1);
363b1994897Sopenharmony_ci    }
364b1994897Sopenharmony_ci
365b1994897Sopenharmony_ci    constexpr size_t GetColumnsCount() const
366b1994897Sopenharmony_ci    {
367b1994897Sopenharmony_ci        return NUM_COLUMNS;
368b1994897Sopenharmony_ci    }
369b1994897Sopenharmony_ci
370b1994897Sopenharmony_ci    size_t GetRowsCount() const
371b1994897Sopenharmony_ci    {
372b1994897Sopenharmony_ci        return rows_count_;
373b1994897Sopenharmony_ci    }
374b1994897Sopenharmony_ci
375b1994897Sopenharmony_ci    size_t GetRowSizeInBits() const
376b1994897Sopenharmony_ci    {
377b1994897Sopenharmony_ci        return columns_offsets_[NUM_COLUMNS];
378b1994897Sopenharmony_ci    }
379b1994897Sopenharmony_ci
380b1994897Sopenharmony_ci    size_t GetColumnWidth(size_t index) const
381b1994897Sopenharmony_ci    {
382b1994897Sopenharmony_ci        return columns_offsets_[index + 1] - columns_offsets_[index];
383b1994897Sopenharmony_ci    }
384b1994897Sopenharmony_ci
385b1994897Sopenharmony_ci    uint32_t ReadColumn(size_t row_index, size_t column) const
386b1994897Sopenharmony_ci    {
387b1994897Sopenharmony_ci        ASSERT(column < GetColumnsCount());
388b1994897Sopenharmony_ci        return region_.Read(row_index * GetRowSizeInBits() + columns_offsets_[column], GetColumnWidth(column)) +
389b1994897Sopenharmony_ci               NO_VALUE_DIFF;
390b1994897Sopenharmony_ci    }
391b1994897Sopenharmony_ci
392b1994897Sopenharmony_ci    auto GetRow(size_t index)
393b1994897Sopenharmony_ci    {
394b1994897Sopenharmony_ci        ASSERT(index < GetRowsCount());
395b1994897Sopenharmony_ci        return Accessor(this, index);
396b1994897Sopenharmony_ci    }
397b1994897Sopenharmony_ci
398b1994897Sopenharmony_ci    auto GetRow(size_t index) const
399b1994897Sopenharmony_ci    {
400b1994897Sopenharmony_ci        ASSERT(index < GetRowsCount());
401b1994897Sopenharmony_ci        return Accessor(this, index);
402b1994897Sopenharmony_ci    }
403b1994897Sopenharmony_ci
404b1994897Sopenharmony_ci    auto GetInvalidRow() const
405b1994897Sopenharmony_ci    {
406b1994897Sopenharmony_ci        return Accessor(this, -1);
407b1994897Sopenharmony_ci    }
408b1994897Sopenharmony_ci
409b1994897Sopenharmony_ci    RegionType GetBitMemoryRegion(uint32_t row) const
410b1994897Sopenharmony_ci    {
411b1994897Sopenharmony_ci        if (row == NO_VALUE) {
412b1994897Sopenharmony_ci            return RegionType();
413b1994897Sopenharmony_ci        }
414b1994897Sopenharmony_ci        size_t offset = row * GetRowSizeInBits() + columns_offsets_[0];
415b1994897Sopenharmony_ci        return region_.Subregion(offset, GetColumnWidth(0));
416b1994897Sopenharmony_ci    }
417b1994897Sopenharmony_ci
418b1994897Sopenharmony_ci    void Decode(BitMemoryStreamIn *stream)
419b1994897Sopenharmony_ci    {
420b1994897Sopenharmony_ci        auto columns = VarintPack::Read<NUM_COLUMNS + 1>(stream);
421b1994897Sopenharmony_ci        rows_count_ = columns[NUM_COLUMNS];
422b1994897Sopenharmony_ci
423b1994897Sopenharmony_ci        // Calculate offsets
424b1994897Sopenharmony_ci        columns_offsets_[0] = 0;
425b1994897Sopenharmony_ci        for (size_t i = 0; i < NUM_COLUMNS; i++) {
426b1994897Sopenharmony_ci            columns_offsets_[i + 1] = columns_offsets_[i] + columns[i];
427b1994897Sopenharmony_ci        }
428b1994897Sopenharmony_ci
429b1994897Sopenharmony_ci        region_ = stream->ReadRegion(GetRowsCount() * GetRowSizeInBits());
430b1994897Sopenharmony_ci    }
431b1994897Sopenharmony_ci
432b1994897Sopenharmony_ci    void Dump(std::ostream &out = std::cout) const
433b1994897Sopenharmony_ci    {
434b1994897Sopenharmony_ci        out << "BitTable: " << Accessor::TABLE_NAME << ", rows=" << GetRowsCount()
435b1994897Sopenharmony_ci            << ", row_size=" << GetRowSizeInBits() << std::endl;
436b1994897Sopenharmony_ci        static constexpr size_t INDENT = 4;
437b1994897Sopenharmony_ci        std::array<uint32_t, NUM_COLUMNS> width {};
438b1994897Sopenharmony_ci        out << "    ";
439b1994897Sopenharmony_ci        for (size_t i = 0; i < NUM_COLUMNS; i++) {
440b1994897Sopenharmony_ci            out << GetColumnName(i) << " ";
441b1994897Sopenharmony_ci            width[i] = strlen(GetColumnName(i)) + 1;
442b1994897Sopenharmony_ci        }
443b1994897Sopenharmony_ci        out << std::endl;
444b1994897Sopenharmony_ci        int index = 0;
445b1994897Sopenharmony_ci        for (auto row : *this) {
446b1994897Sopenharmony_ci            static constexpr size_t INDEX_WIDTH = 2;
447b1994897Sopenharmony_ci            out << std::right << std::setw(INDEX_WIDTH) << index++ << ": ";
448b1994897Sopenharmony_ci            for (size_t i = 0; i < NUM_COLUMNS; i++) {
449b1994897Sopenharmony_ci                std::string indent(INDENT, ' ');
450b1994897Sopenharmony_ci                out << std::left << std::setw(width[i]);
451b1994897Sopenharmony_ci                out << row.GetColumnStr(i);
452b1994897Sopenharmony_ci            }
453b1994897Sopenharmony_ci            out << std::endl;
454b1994897Sopenharmony_ci        }
455b1994897Sopenharmony_ci    }
456b1994897Sopenharmony_ci
457b1994897Sopenharmony_ci    const char *GetColumnName(size_t index) const
458b1994897Sopenharmony_ci    {
459b1994897Sopenharmony_ci        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
460b1994897Sopenharmony_ci        return GetBitTableColumnNamesImpl<Accessor>(std::make_index_sequence<NUM_COLUMNS>())[index];
461b1994897Sopenharmony_ci    }
462b1994897Sopenharmony_ci
463b1994897Sopenharmony_ciprivate:
464b1994897Sopenharmony_ci    BitMemoryRegion<const uint8_t> region_;
465b1994897Sopenharmony_ci    std::array<uint16_t, NUM_COLUMNS + 1> columns_offsets_ {};
466b1994897Sopenharmony_ci    uint16_t rows_count_ {0};
467b1994897Sopenharmony_ci};
468b1994897Sopenharmony_ci
469b1994897Sopenharmony_citemplate <typename Accessor>
470b1994897Sopenharmony_ciclass BitTableBuilder {
471b1994897Sopenharmony_cipublic:
472b1994897Sopenharmony_ci    static constexpr size_t NUM_COLUMNS = Accessor::NUM_COLUMNS;
473b1994897Sopenharmony_ci    static constexpr uint32_t NO_VALUE = BitTable<Accessor>::NO_VALUE;
474b1994897Sopenharmony_ci    static constexpr uint32_t NO_VALUE_DIFF = BitTable<Accessor>::NO_VALUE_DIFF;
475b1994897Sopenharmony_ci
476b1994897Sopenharmony_ci    class Entry {
477b1994897Sopenharmony_ci    public:
478b1994897Sopenharmony_ci        Entry()
479b1994897Sopenharmony_ci        {
480b1994897Sopenharmony_ci            std::fill(data_.begin(), data_.end(), NO_VALUE);
481b1994897Sopenharmony_ci        }
482b1994897Sopenharmony_ci
483b1994897Sopenharmony_ci        Entry(std::initializer_list<uint32_t> data)
484b1994897Sopenharmony_ci        {
485b1994897Sopenharmony_ci            std::copy(data.begin(), data.end(), data_.begin());
486b1994897Sopenharmony_ci        }
487b1994897Sopenharmony_ci
488b1994897Sopenharmony_ci        uint32_t operator[](size_t index) const
489b1994897Sopenharmony_ci        {
490b1994897Sopenharmony_ci            return data_[index];
491b1994897Sopenharmony_ci        }
492b1994897Sopenharmony_ci
493b1994897Sopenharmony_ci        uint32_t &operator[](size_t index)
494b1994897Sopenharmony_ci        {
495b1994897Sopenharmony_ci            return data_[index];
496b1994897Sopenharmony_ci        }
497b1994897Sopenharmony_ci
498b1994897Sopenharmony_ci        bool operator==(const Entry &rhs) const
499b1994897Sopenharmony_ci        {
500b1994897Sopenharmony_ci            return data_ == rhs.data_;
501b1994897Sopenharmony_ci        }
502b1994897Sopenharmony_ci
503b1994897Sopenharmony_ci        void SetColumn(size_t index, uint32_t value)
504b1994897Sopenharmony_ci        {
505b1994897Sopenharmony_ci            data_[index] = value;
506b1994897Sopenharmony_ci        }
507b1994897Sopenharmony_ci
508b1994897Sopenharmony_ci        template <typename... Args>
509b1994897Sopenharmony_ci        void SetColumns(Args... values)
510b1994897Sopenharmony_ci        {
511b1994897Sopenharmony_ci            static_assert(sizeof...(Args) == NUM_COLUMNS);
512b1994897Sopenharmony_ci            int i = 0;
513b1994897Sopenharmony_ci            (SetColumn(i++, values), ...);
514b1994897Sopenharmony_ci        }
515b1994897Sopenharmony_ci
516b1994897Sopenharmony_ci        ~Entry() = default;
517b1994897Sopenharmony_ci
518b1994897Sopenharmony_ci        DEFAULT_COPY_SEMANTIC(Entry);
519b1994897Sopenharmony_ci        DEFAULT_NOEXCEPT_MOVE_SEMANTIC(Entry);
520b1994897Sopenharmony_ci
521b1994897Sopenharmony_ci    private:
522b1994897Sopenharmony_ci        std::array<uint32_t, NUM_COLUMNS> data_;
523b1994897Sopenharmony_ci    };
524b1994897Sopenharmony_ci
525b1994897Sopenharmony_cipublic:
526b1994897Sopenharmony_ci    explicit BitTableBuilder(ArenaAllocator *allocator)
527b1994897Sopenharmony_ci        : entries_(allocator->Adapter()), dedup_map_(allocator->Adapter())
528b1994897Sopenharmony_ci    {
529b1994897Sopenharmony_ci    }
530b1994897Sopenharmony_ci
531b1994897Sopenharmony_ci    size_t GetRowsCount() const
532b1994897Sopenharmony_ci    {
533b1994897Sopenharmony_ci        return entries_.size();
534b1994897Sopenharmony_ci    }
535b1994897Sopenharmony_ci
536b1994897Sopenharmony_ci    const Entry &GetLast() const
537b1994897Sopenharmony_ci    {
538b1994897Sopenharmony_ci        return entries_.back();
539b1994897Sopenharmony_ci    }
540b1994897Sopenharmony_ci
541b1994897Sopenharmony_ci    const Entry &GetEntry(size_t index) const
542b1994897Sopenharmony_ci    {
543b1994897Sopenharmony_ci        return entries_[index];
544b1994897Sopenharmony_ci    }
545b1994897Sopenharmony_ci
546b1994897Sopenharmony_ci    size_t GetSize() const
547b1994897Sopenharmony_ci    {
548b1994897Sopenharmony_ci        return entries_.size();
549b1994897Sopenharmony_ci    }
550b1994897Sopenharmony_ci
551b1994897Sopenharmony_ci    ALWAYS_INLINE void Emplace(Entry entry)
552b1994897Sopenharmony_ci    {
553b1994897Sopenharmony_ci        entries_.emplace_back(entry);
554b1994897Sopenharmony_ci    }
555b1994897Sopenharmony_ci
556b1994897Sopenharmony_ci    ALWAYS_INLINE size_t Add(Entry entry)
557b1994897Sopenharmony_ci    {
558b1994897Sopenharmony_ci        return AddArray(Span(&entry, 1));
559b1994897Sopenharmony_ci    }
560b1994897Sopenharmony_ci
561b1994897Sopenharmony_ci    size_t AddArray(Span<Entry> entries)
562b1994897Sopenharmony_ci    {
563b1994897Sopenharmony_ci        uint32_t hash = FnvHash(entries.template SubSpan<uint32_t>(0, entries.size() * NUM_COLUMNS));
564b1994897Sopenharmony_ci        auto range = dedup_map_.equal_range(hash);
565b1994897Sopenharmony_ci        for (auto it = range.first; it != range.second; ++it) {
566b1994897Sopenharmony_ci            uint32_t row = it->second;
567b1994897Sopenharmony_ci            if (entries.size() + row <= entries_.size() &&
568b1994897Sopenharmony_ci                std::equal(entries.begin(), entries.end(), entries_.begin() + row)) {
569b1994897Sopenharmony_ci                return row;
570b1994897Sopenharmony_ci            }
571b1994897Sopenharmony_ci        }
572b1994897Sopenharmony_ci        uint32_t row = GetRowsCount();
573b1994897Sopenharmony_ci        entries_.insert(entries_.end(), entries.begin(), entries.end());
574b1994897Sopenharmony_ci        dedup_map_.emplace(hash, row);
575b1994897Sopenharmony_ci        return row;
576b1994897Sopenharmony_ci    }
577b1994897Sopenharmony_ci
578b1994897Sopenharmony_ci    void CalculateColumnsWidth(Span<uint32_t> columns_width)
579b1994897Sopenharmony_ci    {
580b1994897Sopenharmony_ci        std::fill(columns_width.begin(), columns_width.end(), 0);
581b1994897Sopenharmony_ci        for (const auto &entry : entries_) {
582b1994897Sopenharmony_ci            for (size_t i = 0; i < NUM_COLUMNS; i++) {
583b1994897Sopenharmony_ci                columns_width[i] |= entry[i] - NO_VALUE_DIFF;
584b1994897Sopenharmony_ci            }
585b1994897Sopenharmony_ci        }
586b1994897Sopenharmony_ci        for (auto &value : columns_width) {
587b1994897Sopenharmony_ci            value = MinimumBitsToStore(value);
588b1994897Sopenharmony_ci        }
589b1994897Sopenharmony_ci    }
590b1994897Sopenharmony_ci
591b1994897Sopenharmony_ci    template <typename Container>
592b1994897Sopenharmony_ci    void Encode(BitMemoryStreamOut<Container> &stream)
593b1994897Sopenharmony_ci    {
594b1994897Sopenharmony_ci        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
595b1994897Sopenharmony_ci        std::array<uint32_t, NUM_COLUMNS + 1> columns_width;
596b1994897Sopenharmony_ci        CalculateColumnsWidth(Span(columns_width.data(), NUM_COLUMNS));
597b1994897Sopenharmony_ci        columns_width[NUM_COLUMNS] = entries_.size();
598b1994897Sopenharmony_ci        VarintPack::Write(stream, columns_width);
599b1994897Sopenharmony_ci
600b1994897Sopenharmony_ci        for (const auto &entry : entries_) {
601b1994897Sopenharmony_ci            for (size_t i = 0; i < NUM_COLUMNS; i++) {
602b1994897Sopenharmony_ci                stream.Write(entry[i] - NO_VALUE_DIFF, columns_width[i]);
603b1994897Sopenharmony_ci            }
604b1994897Sopenharmony_ci        }
605b1994897Sopenharmony_ci    }
606b1994897Sopenharmony_ci
607b1994897Sopenharmony_ci    virtual ~BitTableBuilder() = default;
608b1994897Sopenharmony_ci
609b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(BitTableBuilder);
610b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(BitTableBuilder);
611b1994897Sopenharmony_ci
612b1994897Sopenharmony_ciprivate:
613b1994897Sopenharmony_ci    ArenaDeque<Entry> entries_;
614b1994897Sopenharmony_ci    ArenaUnorderedMultiMap<uint32_t, uint32_t> dedup_map_;
615b1994897Sopenharmony_ci};
616b1994897Sopenharmony_ci
617b1994897Sopenharmony_ciclass BitmapTableBuilder {
618b1994897Sopenharmony_cipublic:
619b1994897Sopenharmony_ci    using Entry = std::pair<uint32_t *, uint32_t>;
620b1994897Sopenharmony_ci
621b1994897Sopenharmony_ci    explicit BitmapTableBuilder(ArenaAllocator *allocator)
622b1994897Sopenharmony_ci        : allocator_(allocator), rows_(allocator->Adapter()), dedup_map_(allocator->Adapter())
623b1994897Sopenharmony_ci    {
624b1994897Sopenharmony_ci    }
625b1994897Sopenharmony_ci
626b1994897Sopenharmony_ci    size_t GetRowsCount() const
627b1994897Sopenharmony_ci    {
628b1994897Sopenharmony_ci        return rows_.size();
629b1994897Sopenharmony_ci    }
630b1994897Sopenharmony_ci
631b1994897Sopenharmony_ci    auto GetEntry(size_t index) const
632b1994897Sopenharmony_ci    {
633b1994897Sopenharmony_ci        return BitMemoryRegion<uint32_t>(rows_[index].first, rows_[index].second);
634b1994897Sopenharmony_ci    }
635b1994897Sopenharmony_ci
636b1994897Sopenharmony_ci    size_t Add(BitVectorSpan vec)
637b1994897Sopenharmony_ci    {
638b1994897Sopenharmony_ci        if (vec.empty()) {
639b1994897Sopenharmony_ci            return BitTableDefault<1>::NO_VALUE;
640b1994897Sopenharmony_ci        }
641b1994897Sopenharmony_ci        uint32_t hash = FnvHash(vec.GetContainerDataSpan());
642b1994897Sopenharmony_ci        auto range = dedup_map_.equal_range(hash);
643b1994897Sopenharmony_ci        for (auto it = range.first; it != range.second; ++it) {
644b1994897Sopenharmony_ci            auto &row = rows_[it->second];
645b1994897Sopenharmony_ci            if (BitVectorSpan(row.first, row.second) == vec) {
646b1994897Sopenharmony_ci                return it->second;
647b1994897Sopenharmony_ci            }
648b1994897Sopenharmony_ci        }
649b1994897Sopenharmony_ci        size_t vec_size_in_bytes = BitsToBytesRoundUp(vec.size());
650b1994897Sopenharmony_ci        size_t data_size_in_bytes = RoundUp(vec_size_in_bytes, sizeof(uint32_t));
651b1994897Sopenharmony_ci        auto data = allocator_->AllocArray<uint32_t>(data_size_in_bytes / sizeof(uint32_t));
652b1994897Sopenharmony_ci        if (data_size_in_bytes != 0) {
653b1994897Sopenharmony_ci            errno_t res = memcpy_s(data, vec_size_in_bytes, vec.data(), vec_size_in_bytes);
654b1994897Sopenharmony_ci            if (res != EOK) {
655b1994897Sopenharmony_ci                UNREACHABLE();
656b1994897Sopenharmony_ci            }
657b1994897Sopenharmony_ci        }
658b1994897Sopenharmony_ci
659b1994897Sopenharmony_ci        // Clear extra bytes, which are not be covered by vector's data
660b1994897Sopenharmony_ci        size_t extra_bytes = data_size_in_bytes - vec_size_in_bytes;
661b1994897Sopenharmony_ci        if (extra_bytes != 0) {
662b1994897Sopenharmony_ci            // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic,-warnings-as-errors)
663b1994897Sopenharmony_ci            memset_s(reinterpret_cast<uint8_t *>(data) + vec_size_in_bytes, extra_bytes, 0, extra_bytes);
664b1994897Sopenharmony_ci        }
665b1994897Sopenharmony_ci        uint32_t index = rows_.size();
666b1994897Sopenharmony_ci        rows_.push_back({data, vec.size()});
667b1994897Sopenharmony_ci        dedup_map_.emplace(hash, index);
668b1994897Sopenharmony_ci        return index;
669b1994897Sopenharmony_ci    }
670b1994897Sopenharmony_ci
671b1994897Sopenharmony_ci    template <typename Container>
672b1994897Sopenharmony_ci    void Encode(BitMemoryStreamOut<Container> &stream)
673b1994897Sopenharmony_ci    {
674b1994897Sopenharmony_ci        static constexpr size_t COLUMNS_SIZE = 2;
675b1994897Sopenharmony_ci        std::array<uint32_t, COLUMNS_SIZE> columns = {0, static_cast<uint32_t>(rows_.size())};
676b1994897Sopenharmony_ci        std::for_each(rows_.begin(), rows_.end(),
677b1994897Sopenharmony_ci                      [&columns](const auto &row) { columns[0] = std::max(columns[0], row.second); });
678b1994897Sopenharmony_ci        VarintPack::Write(stream, columns);
679b1994897Sopenharmony_ci
680b1994897Sopenharmony_ci        for (const auto &row : rows_) {
681b1994897Sopenharmony_ci            stream.Write(row.first, row.second, columns[0]);
682b1994897Sopenharmony_ci        }
683b1994897Sopenharmony_ci    }
684b1994897Sopenharmony_ci
685b1994897Sopenharmony_ci    virtual ~BitmapTableBuilder() = default;
686b1994897Sopenharmony_ci
687b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(BitmapTableBuilder);
688b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(BitmapTableBuilder);
689b1994897Sopenharmony_ci
690b1994897Sopenharmony_ciprivate:
691b1994897Sopenharmony_ci    ArenaAllocator *allocator_ {nullptr};
692b1994897Sopenharmony_ci    ArenaDeque<Entry> rows_;
693b1994897Sopenharmony_ci    ArenaUnorderedMultiMap<uint32_t, uint32_t> dedup_map_;
694b1994897Sopenharmony_ci};
695b1994897Sopenharmony_ci
696b1994897Sopenharmony_ci}  // namespace panda
697b1994897Sopenharmony_ci
698b1994897Sopenharmony_ci#endif  // LIBPANDABASE_UTILS_BIT_TABLE_H
699