/*
 * Copyright (C) 2013 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.
 */

#ifndef ART_COMPILER_DEX_ARENA_BIT_VECTOR_H_
#define ART_COMPILER_DEX_ARENA_BIT_VECTOR_H_

#include <stdint.h>
#include <stddef.h>
#include "compiler_enums.h"
#include "arena_allocator.h"

namespace art {

/*
 * Expanding bitmap, used for tracking resources.  Bits are numbered starting
 * from zero.  All operations on a BitVector are unsynchronized.
 */
class ArenaBitVector {
  public:
    class Iterator {
      public:
        explicit Iterator(ArenaBitVector* bit_vector)
          : p_bits_(bit_vector),
            bit_storage_(bit_vector->GetRawStorage()),
            bit_index_(0),
            bit_size_(p_bits_->storage_size_ * sizeof(uint32_t) * 8) {};

        // Return the position of the next set bit.  -1 means end-of-element reached.
        int Next() {
          // Did anything obviously change since we started?
          DCHECK_EQ(bit_size_, p_bits_->GetStorageSize() * sizeof(uint32_t) * 8);
          DCHECK_EQ(bit_storage_, p_bits_->GetRawStorage());

          if (bit_index_ >= bit_size_) return -1;

          uint32_t word_index = bit_index_ / 32;
          uint32_t word = bit_storage_[word_index];
          // Mask out any bits in the first word we've already considered.
          word >>= bit_index_ & 0x1f;
          if (word == 0) {
            bit_index_ &= ~0x1f;
            do {
              word_index++;
              if ((word_index * 32) >= bit_size_) {
                bit_index_ = bit_size_;
                return -1;
              }
              word = bit_storage_[word_index];
              bit_index_ += 32;
            } while (word == 0);
          }
          bit_index_ += CTZ(word) + 1;
          return bit_index_ - 1;
        }

        static void* operator new(size_t size, ArenaAllocator* arena) {
          return arena->NewMem(sizeof(ArenaBitVector::Iterator), true,
                               ArenaAllocator::kAllocGrowableBitMap);
        };
        static void operator delete(void* p) {};  // Nop.

      private:
        ArenaBitVector* const p_bits_;
        uint32_t* const bit_storage_;
        uint32_t bit_index_;              // Current index (size in bits).
        const uint32_t bit_size_;       // Size of vector in bits.
    };

    ArenaBitVector(ArenaAllocator* arena, unsigned int start_bits, bool expandable,
                   OatBitMapKind kind = kBitMapMisc);
    ~ArenaBitVector() {};

    static void* operator new(size_t size, ArenaAllocator* arena) {
      return arena->NewMem(sizeof(ArenaBitVector), true, ArenaAllocator::kAllocGrowableBitMap);
    }
    static void operator delete(void* p) {};  // Nop.

    void SetBit(unsigned int num);
    void ClearBit(unsigned int num);
    void MarkAllBits(bool set);
    void DebugBitVector(char* msg, int length);
    bool IsBitSet(unsigned int num);
    void ClearAllBits();
    void SetInitialBits(unsigned int num_bits);
    void Copy(ArenaBitVector* src);
    void Intersect(const ArenaBitVector* src2);
    void Union(const ArenaBitVector* src);
    // Are we equal to another bit vector?  Note: expandability attributes must also match.
    bool Equal(const ArenaBitVector* src) {
      return (storage_size_ == src->GetStorageSize()) &&
        (expandable_ == src->IsExpandable()) &&
        (memcmp(storage_, src->GetRawStorage(), storage_size_ * 4) == 0);
    }
    int NumSetBits();

    uint32_t GetStorageSize() const { return storage_size_; }
    bool IsExpandable() const { return expandable_; }
    uint32_t GetRawStorageWord(size_t idx) const { return storage_[idx]; }
    uint32_t* GetRawStorage() { return storage_; }
    const uint32_t* GetRawStorage() const { return storage_; }

  private:
    ArenaAllocator* const arena_;
    const bool expandable_;         // expand bitmap if we run out?
    const OatBitMapKind kind_;      // for memory use tuning.
    uint32_t   storage_size_;       // current size, in 32-bit words.
    uint32_t*  storage_;
};


}  // namespace art

#endif  // ART_COMPILER_DEX_ARENA_BIT_VECTOR_H_
