// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/bitmap.h"

#include "platform/assert.h"
#include "vm/object.h"

namespace dart {

void BitmapBuilder::SetLength(intptr_t new_length) {
  // When this function is used to shorten the length, affected bits in the
  // backing store need to be cleared because the implementation assumes it.
  if (new_length < length_) {
    // Byte offset containing the first bit to be cleared.
    intptr_t byte_offset = new_length >> kBitsPerByteLog2;
    if (byte_offset < data_size_in_bytes_) {
      // First bit index (in the byte) to be cleared.
      intptr_t bit_index = new_length & (kBitsPerByte - 1);
      intptr_t mask = (1 << bit_index) - 1;
      data_[byte_offset] &= mask;
      // Clear the rest.
      ++byte_offset;
      if (byte_offset < data_size_in_bytes_) {
        memset(&data_[byte_offset], 0, data_size_in_bytes_ - byte_offset);
      }
    }
  }
  length_ = new_length;
}

bool BitmapBuilder::Get(intptr_t bit_offset) const {
  if (!InRange(bit_offset)) {
    return false;
  }
  intptr_t byte_offset = bit_offset >> kBitsPerByteLog2;
  // Bits not covered by the backing store are implicitly false.
  return (byte_offset < data_size_in_bytes_) && GetBit(bit_offset);
}

void BitmapBuilder::Set(intptr_t bit_offset, bool value) {
  if (!InRange(bit_offset)) {
    length_ = bit_offset + 1;
  }

  // Bits not covered by the backing store are implicitly false.
  // Grow the backing store if necessary.
  if (value) {
    if (!InBackingStore(bit_offset)) {
      intptr_t byte_offset = bit_offset >> kBitsPerByteLog2;
      uint8_t* old_data = data_;
      intptr_t old_size = data_size_in_bytes_;
      data_size_in_bytes_ =
          Utils::RoundUp(byte_offset + 1, kIncrementSizeInBytes);
      ASSERT(data_size_in_bytes_ > 0);
      data_ = Thread::Current()->zone()->Alloc<uint8_t>(data_size_in_bytes_);
      ASSERT(data_ != NULL);
      memmove(data_, old_data, old_size);
      memset(&data_[old_size], 0, (data_size_in_bytes_ - old_size));
    }
    ASSERT(InBackingStore(bit_offset));
  }

  // Set bit if in backing store.
  if (InBackingStore(bit_offset)) {
    SetBit(bit_offset, value);
  }
}

void BitmapBuilder::SetRange(intptr_t min, intptr_t max, bool value) {
  for (intptr_t i = min; i <= max; i++) {
    Set(i, value);
  }
}

void BitmapBuilder::Print() const {
  for (intptr_t i = 0; i < Length(); i++) {
    if (Get(i)) {
      OS::PrintErr("1");
    } else {
      OS::PrintErr("0");
    }
  }
}

void BitmapBuilder::AppendAsBytesTo(BaseWriteStream* stream) const {
  // Early return if there are no bits in the payload to copy.
  if (Length() == 0) return;

  const intptr_t total_size =
      Utils::RoundUp(Length(), kBitsPerByte) / kBitsPerByte;
  intptr_t payload_size;
  intptr_t extra_size;
  if (total_size > data_size_in_bytes_) {
    // A [BitmapBuilder] does not allocate storage for the trailing 0 bits in
    // the backing store, so we need to add additional empty bytes here.
    payload_size = data_size_in_bytes_;
    extra_size = total_size - data_size_in_bytes_;
  } else {
    payload_size = total_size;
    extra_size = 0;
  }
#if defined(DEBUG)
  // Make sure any bits in the payload beyond the bit length if we're not
  // appending trailing zeroes are cleared to ensure deterministic snapshots.
  if (extra_size == 0 && Length() % kBitsPerByte != 0) {
    const int8_t mask = (1 << (Length() % kBitsPerByte)) - 1;
    ASSERT_EQUAL(data_[payload_size - 1], (data_[payload_size - 1] & mask));
  }
#endif
  for (intptr_t i = 0; i < payload_size; i++) {
    stream->WriteByte(data_[i]);
  }
  for (intptr_t i = 0; i < extra_size; i++) {
    stream->WriteByte(0U);
  }
}

bool BitmapBuilder::GetBit(intptr_t bit_offset) const {
  if (!InRange(bit_offset)) {
    return false;
  }
  intptr_t byte_offset = bit_offset >> kBitsPerByteLog2;
  ASSERT(byte_offset < data_size_in_bytes_);
  intptr_t bit_remainder = bit_offset & (kBitsPerByte - 1);
  uint8_t mask = 1U << bit_remainder;
  ASSERT(data_ != NULL);
  return ((data_[byte_offset] & mask) != 0);
}

void BitmapBuilder::SetBit(intptr_t bit_offset, bool value) {
  if (!InRange(bit_offset)) {
    FATAL1(
        "Fatal error in BitmapBuilder::SetBit :"
        " invalid bit_offset, %" Pd "\n",
        bit_offset);
  }
  intptr_t byte_offset = bit_offset >> kBitsPerByteLog2;
  ASSERT(byte_offset < data_size_in_bytes_);
  intptr_t bit_remainder = bit_offset & (kBitsPerByte - 1);
  uint8_t mask = 1U << bit_remainder;
  ASSERT(data_ != NULL);
  if (value) {
    data_[byte_offset] |= mask;
  } else {
    data_[byte_offset] &= ~mask;
  }
}

}  // namespace dart
