/root/doris/be/src/util/bitmap.cpp
| Line | Count | Source | 
| 1 |  | // Licensed to the Apache Software Foundation (ASF) under one | 
| 2 |  | // or more contributor license agreements.  See the NOTICE file | 
| 3 |  | // distributed with this work for additional information | 
| 4 |  | // regarding copyright ownership.  The ASF licenses this file | 
| 5 |  | // to you under the Apache License, Version 2.0 (the | 
| 6 |  | // "License"); you may not use this file except in compliance | 
| 7 |  | // with the License.  You may obtain a copy of the License at | 
| 8 |  | // | 
| 9 |  | //   http://www.apache.org/licenses/LICENSE-2.0 | 
| 10 |  | // | 
| 11 |  | // Unless required by applicable law or agreed to in writing, | 
| 12 |  | // software distributed under the License is distributed on an | 
| 13 |  | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| 14 |  | // KIND, either express or implied.  See the License for the | 
| 15 |  | // specific language governing permissions and limitations | 
| 16 |  | // under the License. | 
| 17 |  | // This file is copied from | 
| 18 |  | // https://github.com/apache/impala/blob/branch-2.9.0/be/src/util/bitmap.cpp | 
| 19 |  | // and modified by Doris | 
| 20 |  |  | 
| 21 |  | #include "util/bitmap.h" | 
| 22 |  |  | 
| 23 |  | #include <sstream> | 
| 24 |  | namespace doris { | 
| 25 |  |  | 
| 26 | 0 | std::string Bitmap::DebugString(bool print_bits) const { | 
| 27 | 0 |     int64_t words = BitUtil::round_up(num_bits_, 64) / 64; | 
| 28 | 0 |     std::stringstream ss; | 
| 29 | 0 |     ss << "Size (" << num_bits_ << ") words (" << words << ") "; | 
| 30 | 0 |     if (print_bits) { | 
| 31 | 0 |         for (int i = 0; i < num_bits(); ++i) { | 
| 32 | 0 |             if (Get(i)) { | 
| 33 | 0 |                 ss << "1"; | 
| 34 | 0 |             } else { | 
| 35 | 0 |                 ss << "0"; | 
| 36 | 0 |             } | 
| 37 | 0 |         } | 
| 38 | 0 |     } else { | 
| 39 | 0 |         for (auto v : buffer_) { | 
| 40 | 0 |             ss << v << "."; | 
| 41 | 0 |         } | 
| 42 | 0 |     } | 
| 43 | 0 |     ss << std::endl; | 
| 44 | 0 |     return ss.str(); | 
| 45 | 0 | } | 
| 46 |  |  | 
| 47 | 1 | void BitmapChangeBits(uint8_t* bitmap, size_t offset, size_t num_bits, bool value) { | 
| 48 | 1 |     DCHECK_GT(num_bits, 0); | 
| 49 |  |  | 
| 50 | 1 |     size_t start_byte = (offset >> 3); | 
| 51 | 1 |     size_t end_byte = (offset + num_bits - 1) >> 3; | 
| 52 | 1 |     int single_byte = (start_byte == end_byte); | 
| 53 |  |  | 
| 54 |  |     // Change the last bits of the first byte | 
| 55 | 1 |     size_t left = offset & 0x7; | 
| 56 | 1 |     size_t right = (single_byte) ? (left + num_bits) : 8; | 
| 57 | 1 |     uint8_t mask = ((0xff << left) & (0xff >> (8 - right))); | 
| 58 | 1 |     if (value) { | 
| 59 | 1 |         bitmap[start_byte++] |= mask; | 
| 60 | 1 |     } else { | 
| 61 | 0 |         bitmap[start_byte++] &= ~mask; | 
| 62 | 0 |     } | 
| 63 |  |  | 
| 64 |  |     // Nothing left... I'm done | 
| 65 | 1 |     if (single_byte) { | 
| 66 | 0 |         return; | 
| 67 | 0 |     } | 
| 68 |  |  | 
| 69 |  |     // change the middle bits | 
| 70 | 1 |     if (end_byte > start_byte) { | 
| 71 | 1 |         const uint8_t pattern8[2] = {0x00, 0xff}; | 
| 72 | 1 |         memset(bitmap + start_byte, pattern8[value], end_byte - start_byte); | 
| 73 | 1 |     } | 
| 74 |  |  | 
| 75 |  |     // change the first bits of the last byte | 
| 76 | 1 |     right = offset + num_bits - (end_byte << 3); | 
| 77 | 1 |     mask = (0xff >> (8 - right)); | 
| 78 | 1 |     if (value) { | 
| 79 | 1 |         bitmap[end_byte] |= mask; | 
| 80 | 1 |     } else { | 
| 81 | 0 |         bitmap[end_byte] &= ~mask; | 
| 82 | 0 |     } | 
| 83 | 1 | } | 
| 84 |  |  | 
| 85 |  | bool BitmapFindFirst(const uint8_t* bitmap, size_t offset, size_t bitmap_size, bool value, | 
| 86 | 451k |                      size_t* idx) { | 
| 87 | 451k |     const uint64_t pattern64[2] = {0xffffffffffffffff, 0x0000000000000000}; | 
| 88 | 451k |     const uint8_t pattern8[2] = {0xff, 0x00}; | 
| 89 | 451k |     size_t bit; | 
| 90 |  |  | 
| 91 | 451k |     DCHECK_LE(offset, bitmap_size); | 
| 92 |  |  | 
| 93 |  |     // Jump to the byte at specified offset | 
| 94 | 451k |     const uint8_t* p = bitmap + (offset >> 3); | 
| 95 | 451k |     size_t num_bits = bitmap_size - offset; | 
| 96 |  |  | 
| 97 |  |     // Find a 'value' bit at the end of the first byte | 
| 98 | 451k |     if ((bit = offset & 0x7)) { | 
| 99 | 21 |         for (; bit < 8 && num_bits > 0; ++bit) { | 
| 100 | 17 |             if (BitmapTest(p, bit) == value) { | 
| 101 | 1 |                 *idx = ((p - bitmap) << 3) + bit; | 
| 102 | 1 |                 return true; | 
| 103 | 1 |             } | 
| 104 |  |  | 
| 105 | 16 |             num_bits--; | 
| 106 | 16 |         } | 
| 107 |  |  | 
| 108 | 4 |         p++; | 
| 109 | 4 |     } | 
| 110 |  |  | 
| 111 |  |     // check 64bit at the time for a 'value' bit | 
| 112 | 451k |     const uint64_t* u64 = (const uint64_t*)p; | 
| 113 | 451k |     while (num_bits >= 64 && *u64 == pattern64[value]) { | 
| 114 | 281 |         num_bits -= 64; | 
| 115 | 281 |         u64++; | 
| 116 | 281 |     } | 
| 117 |  |  | 
| 118 |  |     // check 8bit at the time for a 'value' bit | 
| 119 | 451k |     p = (const uint8_t*)u64; | 
| 120 | 451k |     while (num_bits >= 8 && *p == pattern8[value]) { | 
| 121 | 32 |         num_bits -= 8; | 
| 122 | 32 |         p++; | 
| 123 | 32 |     } | 
| 124 |  |  | 
| 125 |  |     // Find a 'value' bit at the beginning of the last byte | 
| 126 | 902k |     for (bit = 0; num_bits > 0; ++bit) { | 
| 127 | 451k |         if (BitmapTest(p, bit) == value) { | 
| 128 | 7 |             *idx = ((p - bitmap) << 3) + bit; | 
| 129 | 7 |             return true; | 
| 130 | 7 |         } | 
| 131 | 451k |         num_bits--; | 
| 132 | 451k |     } | 
| 133 |  |  | 
| 134 | 451k |     return false; | 
| 135 | 451k | } | 
| 136 |  |  | 
| 137 |  | } // namespace doris |