Finds the first bit that matches the test value. Returns the index of the first matching bit, or -1 if none found. @param test_value The value to search for (true or false) @param offset Starting position to search from (default: 0)
| 234 | /// @param test_value The value to search for (true or false) |
| 235 | /// @param offset Starting position to search from (default: 0) |
| 236 | fl::i32 find_first(bool test_value, fl::u32 offset = 0) const FL_NOEXCEPT { |
| 237 | // If offset is beyond our size, no match possible |
| 238 | if (offset >= N) { |
| 239 | return -1; |
| 240 | } |
| 241 | |
| 242 | // Calculate which block to start from |
| 243 | fl::u32 start_block = offset / bits_per_block; |
| 244 | fl::u32 start_bit = offset % bits_per_block; |
| 245 | |
| 246 | for (fl::u32 block_idx = start_block; block_idx < block_count; ++block_idx) { |
| 247 | block_type current_block = _blocks[block_idx]; |
| 248 | |
| 249 | // For the last block, we need to mask out unused bits |
| 250 | if (block_idx == block_count - 1 && N % bits_per_block != 0) { |
| 251 | const fl::u32 valid_bits = N % bits_per_block; |
| 252 | block_type mask = (valid_bits == bits_per_block) |
| 253 | ? static_cast<block_type>(~block_type(0)) |
| 254 | : ((block_type(1) << valid_bits) - 1); |
| 255 | current_block &= mask; |
| 256 | } |
| 257 | |
| 258 | // If looking for false bits, invert the block |
| 259 | if (!test_value) { |
| 260 | current_block = ~current_block; |
| 261 | } |
| 262 | |
| 263 | // For the first block, mask out bits before the offset |
| 264 | if (block_idx == start_block && start_bit > 0) { |
| 265 | current_block &= ~((block_type(1) << start_bit) - 1); |
| 266 | } |
| 267 | |
| 268 | // If there are any matching bits in this block |
| 269 | if (current_block != 0) { |
| 270 | // Find the first set bit |
| 271 | fl::u32 bit_pos = fl::countr_zero(current_block); |
| 272 | fl::u32 absolute_pos = block_idx * bits_per_block + bit_pos; |
| 273 | |
| 274 | // Make sure we haven't gone past the end of the bitset |
| 275 | if (absolute_pos < N) { |
| 276 | return static_cast<fl::i32>(absolute_pos); |
| 277 | } |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | return -1; // No matching bit found |
| 282 | } |
| 283 | |
| 284 | /// Finds the first run of consecutive bits that match the test value. |
| 285 | /// Returns the index of the first bit in the run, or -1 if no run found. |
no test coverage detected