// 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. // This file is copied from // https://github.com/apache/impala/blob/branch-2.9.0/be/src/util/bitmap.cpp // and modified by Doris #include "util/bitmap.h" #include #include "gutil/stringprintf.h" namespace doris { std::string Bitmap::DebugString(bool print_bits) const { int64_t words = BitUtil::round_up(num_bits_, 64) / 64; std::stringstream ss; ss << "Size (" << num_bits_ << ") words (" << words << ") "; if (print_bits) { for (int i = 0; i < num_bits(); ++i) { if (Get(i)) { ss << "1"; } else { ss << "0"; } } } else { for (auto v : buffer_) { ss << v << "."; } } ss << std::endl; return ss.str(); } void BitmapChangeBits(uint8_t* bitmap, size_t offset, size_t num_bits, bool value) { DCHECK_GT(num_bits, 0); size_t start_byte = (offset >> 3); size_t end_byte = (offset + num_bits - 1) >> 3; int single_byte = (start_byte == end_byte); // Change the last bits of the first byte size_t left = offset & 0x7; size_t right = (single_byte) ? (left + num_bits) : 8; uint8_t mask = ((0xff << left) & (0xff >> (8 - right))); if (value) { bitmap[start_byte++] |= mask; } else { bitmap[start_byte++] &= ~mask; } // Nothing left... I'm done if (single_byte) { return; } // change the middle bits if (end_byte > start_byte) { const uint8_t pattern8[2] = {0x00, 0xff}; memset(bitmap + start_byte, pattern8[value], end_byte - start_byte); } // change the first bits of the last byte right = offset + num_bits - (end_byte << 3); mask = (0xff >> (8 - right)); if (value) { bitmap[end_byte] |= mask; } else { bitmap[end_byte] &= ~mask; } } bool BitmapFindFirst(const uint8_t* bitmap, size_t offset, size_t bitmap_size, bool value, size_t* idx) { const uint64_t pattern64[2] = {0xffffffffffffffff, 0x0000000000000000}; const uint8_t pattern8[2] = {0xff, 0x00}; size_t bit; DCHECK_LE(offset, bitmap_size); // Jump to the byte at specified offset const uint8_t* p = bitmap + (offset >> 3); size_t num_bits = bitmap_size - offset; // Find a 'value' bit at the end of the first byte if ((bit = offset & 0x7)) { for (; bit < 8 && num_bits > 0; ++bit) { if (BitmapTest(p, bit) == value) { *idx = ((p - bitmap) << 3) + bit; return true; } num_bits--; } p++; } // check 64bit at the time for a 'value' bit const uint64_t* u64 = (const uint64_t*)p; while (num_bits >= 64 && *u64 == pattern64[value]) { num_bits -= 64; u64++; } // check 8bit at the time for a 'value' bit p = (const uint8_t*)u64; while (num_bits >= 8 && *p == pattern8[value]) { num_bits -= 8; p++; } // Find a 'value' bit at the beginning of the last byte for (bit = 0; num_bits > 0; ++bit) { if (BitmapTest(p, bit) == value) { *idx = ((p - bitmap) << 3) + bit; return true; } num_bits--; } return false; } std::string BitmapToString(const uint8_t* bitmap, size_t num_bits) { std::string s; size_t index = 0; while (index < num_bits) { StringAppendF(&s, "%4zu: ", index); for (int i = 0; i < 8 && index < num_bits; ++i) { for (int j = 0; j < 8 && index < num_bits; ++j) { StringAppendF(&s, "%d", BitmapTest(bitmap, index)); index++; } StringAppendF(&s, " "); } StringAppendF(&s, "\n"); } return s; } } // namespace doris