/* * Copyright (C) 2021-present ScyllaDB */ /* * SPDX-License-Identifier: AGPL-3.0-or-later */ #pragma once #include #include "utils/compact-radix-tree.hh" namespace compact_radix_tree { template class printer { using tree_t = tree; using node_head_t = typename tree_t::node_head; using leaf_node_t = typename tree_t::leaf_node; using inner_node_t = typename tree_t::inner_node; using layout = typename tree_t::layout; static std::string node_id(const node_head_t& n) { return fmt::format("{:03x}", (reinterpret_cast(&n)>>3) & 0xfff); } static std::string format(const T& val) noexcept { return fmt::format("{}", val); } static std::string format(const typename tree_t::node_head_ptr& p) noexcept { return node_id(*(p.raw())); } template static void print_indirect(const node_head_t& head, const Tbl& table, unsigned depth, std::string id) { fmt::print("{:<{}}{}.ind{} nr={} depth={} prefix={}.{}:", " ", int(depth * 2), id, Tbl::size, head._size, depth, head._prefix & tree_t::prefix_mask, head.prefix_len()); for (unsigned i = 0; i < Tbl::size; i++) { if (table.has(i)) { fmt::print(" [{}] {}:{}", i, table._idx[i], format(table._slots[i])); } } fmt::print("\n"); } template static void print_direct(const node_head_t& head, const Arr& array, unsigned depth, std::string id) { unsigned cap = head._base_layout == layout::direct_static ? tree_t::node_index_limit : head._capacity; fmt::print("{:<{}}{}.dir{} nr={} depth={} prefix={}.{}:", " ", int(depth * 2), id, cap, array._data.count(head), depth, head._prefix & tree_t::prefix_mask, head.prefix_len()); for (unsigned i = 0; i < cap; i++) { if (array._data.has(i)) { fmt::print(" [{}] {}", i, format(array._data._slots[i])); } } fmt::print("\n"); } template static void print(const NT& n, unsigned depth) { switch (n._base._head._base_layout) { case layout::indirect_tiny: return print_indirect(n._base._head, n._base._layouts._this, depth, node_id(n._base._head)); case layout::indirect_small: return print_indirect(n._base._head, n._base._layouts._other._this, depth, node_id(n._base._head)); case layout::indirect_medium: return print_indirect(n._base._head, n._base._layouts._other._other._this, depth, node_id(n._base._head)); case layout::indirect_large: return print_indirect(n._base._head, n._base._layouts._other._other._other._this, depth, node_id(n._base._head)); case layout::direct_static: return print_direct(n._base._head, n._base._layouts._other._other._other._other._this, depth, node_id(n._base._head)); default: break; } __builtin_unreachable(); } static void print(const inner_node_t& n, unsigned depth) { switch (n._base._head._base_layout) { case layout::direct_dynamic: return print_direct(n._base._head, n._base._layouts._this, depth, node_id(n._base._head)); default: break; } __builtin_unreachable(); } static void print(const node_head_t& n, unsigned depth) { if (depth == tree_t::leaf_depth) { print(n.template as_node(), depth); } else { print(n.template as_node(), depth); } } public: static void show(const tree_t& t) { struct printing_visitor { bool sorted = false; bool operator()(Idx idx, const T& val) { std::abort(); } bool operator()(const node_head_t& n, unsigned depth, bool enter) { if (enter) { print(n, depth); } return depth != tree_t::leaf_depth; } }; fmt::print("tree:\n"); t.visit(printing_visitor{}); fmt::print("---\n"); } }; } // namespace