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