#include #include "xcdat/DacBc.hpp" namespace xcdat { DacBc::DacBc(std::istream& is) { for (size_t i = 0; i < sizeof(id_type); ++i) { values_[i] = Vector(is); } for (size_t i = 0; i < sizeof(id_type) - 1; ++i) { flags_[i] = BitVector(is); } leaf_flags_ = BitVector(is); links_ = FitVector(is); max_level_ = read_value(is); num_free_nodes_ = read_value(is); } DacBc::DacBc(const std::vector& bc, BitVectorBuilder& leaf_flags) { if (bc.empty()) { return; } std::vector values[sizeof(id_type)]; BitVectorBuilder flags[sizeof(id_type)]; std::vector links; leaf_flags_ = BitVector(leaf_flags, true, false); values[0].reserve(bc.size() * 2); flags[0].reserve(bc.size() * 2); links.reserve(bc.size()); max_level_ = 0; auto append = [&](id_type value) { uint8_t level = 0; values[level].push_back(static_cast(value & 0xFF)); flags[level].push_back(true); value >>= 8; while (value) { ++level; values[level].push_back(static_cast(value & 0xFF)); flags[level].push_back(true); value >>= 8; } flags[level].set_bit(flags[level].size() - 1, false); max_level_ = std::max(max_level_, level); }; auto append_leaf = [&](id_type value) { links.push_back(value >> 8); values[0].push_back(static_cast(value & 0xFF)); flags[0].push_back(false); }; for (id_type i = 0; i < bc.size(); ++i) { if (leaf_flags_[i]) { append_leaf(bc[i].base); } else { append(bc[i].base ^ i); } append(bc[i].check ^ i); if (bc[i].check == i) { ++num_free_nodes_; } } // release for (uint8_t i = 0; i < max_level_; ++i) { values_[i] = Vector(values[i]); flags_[i] = BitVector(flags[i], true, false); } values_[max_level_] = Vector(values[max_level_]); links_ = FitVector(links); } size_t DacBc::size_in_bytes() const { size_t ret = 0; for (auto& values : values_) { ret += values.size_in_bytes(); } for (auto& flags : flags_) { ret += flags.size_in_bytes(); } ret += leaf_flags_.size_in_bytes(); ret += links_.size_in_bytes(); ret += sizeof(max_level_); ret += sizeof(num_free_nodes_); return ret; } void DacBc::show_stat(std::ostream& os) const { const auto total_size = size_in_bytes(); os << "basic statistics of xcdat::DacBc" << std::endl; show_size("\tnum links: ", links_.size(), os); show_size("\tbytes per node:", double(total_size) / num_nodes(), os); os << "member size statistics of xcdat::DacBc" << std::endl; for (int i = 0; i <= max_level_; ++i) { std::ostringstream oss; oss << "\tvalues_L" << i << ":"; show_size_ratio(oss.str().c_str(), values_[i].size_in_bytes(), total_size, os); } for (int i = 0; i < max_level_; ++i) { std::ostringstream oss; oss << "\tflags_L" << i << ": "; show_size_ratio(oss.str().c_str(), flags_[i].size_in_bytes(), total_size, os); } show_size_ratio("\tleaves: ", leaf_flags_.size_in_bytes(), total_size, os); show_size_ratio("\tlinks: ", links_.size_in_bytes(), total_size, os); } void DacBc::write(std::ostream& os) const { for (auto& values : values_) { values.write(os); } for (auto& flags : flags_) { flags.write(os); } leaf_flags_.write(os); links_.write(os); write_value(max_level_, os); write_value(num_free_nodes_, os); } id_type DacBc::access_(id_type i) const { uint8_t level = 0; id_type value = values_[level][i]; while (level < max_level_) { if (!flags_[level][i]) { break; } i = flags_[level].rank(i); ++level; value |= static_cast(values_[level][i]) << (level * 8); } return value; } } //namespace - xcdat