/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed 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.
 */

#include "src/trace_processor/containers/bit_vector_iterators.h"

namespace perfetto {
namespace trace_processor {
namespace internal {

BaseIterator::BaseIterator(BitVector* bv)
    : size_(bv->size()), bv_(bv), block_(bv_->words_.data()) {}

BaseIterator::~BaseIterator() {
  if (size_ > 0) {
    uint32_t block_idx = bv_->IndexToAddress(index_).block_idx;
    uint32_t last_block_idx = bv_->BlockCount() - 1;

    // If |index_| == |size_| and the last index was on a block boundary, we
    // can end up one block past the end of the bitvector. Take the
    // min of the block index and the last block
    OnBlockChange(std::min(block_idx, last_block_idx), last_block_idx);
  }
}

void BaseIterator::OnBlockChange(uint32_t old_block_idx,
                                 uint32_t new_block_idx) {
  if (set_bit_count_diff_ != 0) {
    // If the count of set bits has changed, go through all the counts between
    // the old and new blocks and modify them.
    // We only need to go to new_block and not to the end of the bitvector as
    // the blocks after new_block will either be updated in a future call to
    // OnBlockChange or in the destructor.
    for (uint32_t i = old_block_idx + 1; i <= new_block_idx; ++i) {
      int32_t new_count =
          static_cast<int32_t>(bv_->counts_[i]) + set_bit_count_diff_;
      PERFETTO_DCHECK(new_count >= 0);

      bv_->counts_[i] = static_cast<uint32_t>(new_count);
    }
  }

  // Reset the changed flag and cache the new block.
  is_block_changed_ = false;
  block_ = bv_->BlockFromIndex(new_block_idx);
}

AllBitsIterator::AllBitsIterator(const BitVector* bv)
    : BaseIterator(const_cast<BitVector*>(bv)) {}

SetBitsIterator::SetBitsIterator(const BitVector* bv)
    : BaseIterator(const_cast<BitVector*>(bv)) {
  set_bit_count_ = bv->CountSetBits();

  if (set_bit_count_ > 0) {
    // Read a batch of set bit indices starting at index 0.
    ReadSetBitBatch(0);

    // Fast forward the iterator to the first index in the freshly read
    // batch of set bots.
    SetIndex(batch_[0]);
  }
}

void SetBitsIterator::ReadSetBitBatch(uint32_t start_idx) {
  PERFETTO_DCHECK(set_bit_index_ % kBatchSize == 0);

  uint32_t set_bit_count_until_i = set_bit_index_;
  for (uint32_t i = start_idx; i < size(); ++i) {
    auto addr = BitVector::IndexToAddress(i);

    // Compute the count to the end of the block noting that the last block
    // needs to use |set_bit_count_| and not the next count in the vector
    // because that is OOB.
    uint32_t set_bits_to_end_of_block =
        addr.block_idx == bv().counts_.size() - 1
            ? set_bit_count_
            : bv().counts_[addr.block_idx + 1];

    // Optimization: If the count of set bits to the end of the block is the
    // same as the count to the current index, we can just skip the whole
    // block without iterating through the bits inside.
    if (set_bits_to_end_of_block == set_bit_count_until_i) {
      static constexpr BitVector::BlockOffset kLastBlockOffset = {
          BitVector::Block::kWords - 1, BitVector::BitWord::kBits - 1};

      i = BitVector::AddressToIndex({addr.block_idx, kLastBlockOffset});
      continue;
    }

    // If the bit is not set, just bail out.
    const BitVector::ConstBlock& block =
        bv().ConstBlockFromIndex(addr.block_idx);
    if (!block.IsSet(addr.block_offset))
      continue;

    // Update |batch_| with the index of the current bit.
    uint32_t batch_idx = set_bit_count_until_i++ % kBatchSize;
    batch_[batch_idx] = i;

    // If we've reached as many indicies as the batch can store, just
    // return.
    if (PERFETTO_UNLIKELY(batch_idx == kBatchSize - 1))
      return;
  }

  // We should only get here when we've managed to read all the set bits.
  // End of batch should return from the body of the loop.
  PERFETTO_DCHECK(set_bit_count_until_i == set_bit_count_);
}

}  // namespace internal
}  // namespace trace_processor
}  // namespace perfetto
