// Copyright (c) 2014 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/circular_buffer_shell.h"

#include <stdint.h>

#include <algorithm>

#include "base/logging.h"
#include "build/build_config.h"

#if defined(OS_STARBOARD)
#include "starboard/memory.h"
#define malloc SbMemoryAllocate
#define realloc SbMemoryReallocate
#define free SbMemoryDeallocate
#endif

static inline void* add_to_pointer(void* pointer, size_t amount) {
  return static_cast<uint8_t*>(pointer) + amount;
}

static inline const void* add_to_pointer(const void* pointer, size_t amount) {
  return static_cast<const uint8_t*>(pointer) + amount;
}

namespace base {

CircularBufferShell::CircularBufferShell(
    size_t max_capacity,
    ReserveType reserve_type /*= kDoNotReserve*/)
    : max_capacity_(max_capacity),
      buffer_(NULL),
      capacity_(0),
      length_(0),
      read_position_(0) {
  if (reserve_type == kReserve) {
    base::AutoLock l(lock_);
    IncreaseCapacityTo_Locked(max_capacity_);
  }
}

CircularBufferShell::~CircularBufferShell() {
  Clear();
}

void CircularBufferShell::Clear() {
  base::AutoLock l(lock_);
  if (buffer_ != NULL) {
    free(buffer_);
    buffer_ = NULL;
  }

  capacity_ = 0;
  length_ = 0;
  read_position_ = 0;
}

void CircularBufferShell::Read(void* destination,
                               size_t length,
                               size_t* bytes_read) {
  base::AutoLock l(lock_);
  DCHECK(destination != NULL || length == 0);
  if (destination == NULL)
    length = 0;

  ReadAndAdvanceUnchecked_Locked(destination, length, bytes_read);
}

void CircularBufferShell::Peek(void* destination,
                               size_t length,
                               size_t source_offset,
                               size_t* bytes_peeked) const {
  base::AutoLock l(lock_);
  DCHECK(destination != NULL || length == 0);
  if (destination == NULL)
    length = 0;

  ReadUnchecked_Locked(destination, length, source_offset, bytes_peeked);
}

void CircularBufferShell::Skip(size_t length, size_t* bytes_skipped) {
  base::AutoLock l(lock_);
  ReadAndAdvanceUnchecked_Locked(NULL, length, bytes_skipped);
}

bool CircularBufferShell::Write(const void* source,
                                size_t length,
                                size_t* bytes_written) {
  base::AutoLock l(lock_);
  DCHECK(source != NULL || length == 0);
  if (source == NULL)
    length = 0;

  if (!EnsureCapacityToWrite_Locked(length)) {
    return false;
  }

  size_t produced = 0;
  while (true) {
    size_t remaining = length - produced;

    // In this pass, write up to the contiguous space left.
    size_t to_write =
        std::min(remaining, capacity_ - GetWritePosition_Locked());
    if (to_write == 0)
      break;

    // Copy this segment and do the accounting.
    void* destination = GetWritePointer_Locked();
    const void* src = add_to_pointer(source, produced);
    memcpy(destination, src, to_write);
    length_ += to_write;
    produced += to_write;
  }

  if (bytes_written)
    *bytes_written = produced;
  return true;
}

size_t CircularBufferShell::GetLength() const {
  base::AutoLock l(lock_);
  return length_;
}

void CircularBufferShell::ReadUnchecked_Locked(void* destination,
                                               size_t destination_length,
                                               size_t source_offset,
                                               size_t* bytes_read) const {
  DCHECK(destination != NULL || bytes_read != NULL);

  lock_.AssertAcquired();

  size_t dummy = 0;
  if (!bytes_read) {
    bytes_read = &dummy;
  }

  // Return immediately if the CircularBuffer is empty or if |source_offset| is
  // greater or equal than |length_|.
  if (capacity_ == 0 || source_offset >= length_) {
    *bytes_read = 0;
    return;
  }

  size_t consumed = 0;
  size_t source_length = length_ - source_offset;
  size_t read_position = (read_position_ + source_offset) % capacity_;

  while (true) {
    size_t remaining = std::min(source_length, destination_length - consumed);

    // In this pass, read the remaining data that is contiguous.
    size_t to_read = std::min(remaining, capacity_ - read_position);
    if (to_read == 0)
      break;

    // Copy this segment and do the accounting.
    const void* source = add_to_pointer(buffer_, read_position);
    if (destination) {
      void* dest = add_to_pointer(destination, consumed);
      memcpy(dest, source, to_read);
    }
    source_length -= to_read;
    read_position = (read_position + to_read) % capacity_;
    consumed += to_read;
  }

  *bytes_read = consumed;
}

void CircularBufferShell::ReadAndAdvanceUnchecked_Locked(
    void* destination,
    size_t destination_length,
    size_t* bytes_read) {
  lock_.AssertAcquired();

  size_t dummy = 0;
  if (!bytes_read) {
    bytes_read = &dummy;
  }

  // Return immediately if the CircularBuffer is empty.
  if (capacity_ == 0) {
    *bytes_read = 0;
    return;
  }

  ReadUnchecked_Locked(destination, destination_length, 0, bytes_read);
  length_ -= *bytes_read;
  read_position_ = (read_position_ + *bytes_read) % capacity_;
}

void* CircularBufferShell::GetWritePointer_Locked() const {
  lock_.AssertAcquired();

  return add_to_pointer(buffer_, GetWritePosition_Locked());
}

size_t CircularBufferShell::GetWritePosition_Locked() const {
  lock_.AssertAcquired();

  return (read_position_ + length_) % capacity_;
}

bool CircularBufferShell::EnsureCapacityToWrite_Locked(size_t length) {
  lock_.AssertAcquired();

  if (capacity_ - length_ < length) {
    size_t capacity = std::max(2 * capacity_, length_ + length);
    if (capacity > max_capacity_)
      capacity = max_capacity_;

    // New capacity still won't be enough.
    if (capacity - length_ < length) {
      return false;
    }

    return IncreaseCapacityTo_Locked(capacity);
  }

  return true;
}

bool CircularBufferShell::IncreaseCapacityTo_Locked(size_t capacity) {
  lock_.AssertAcquired();

  if (capacity <= capacity_) {
    return true;
  }

  // If the data isn't wrapped, we can just use realloc.
  if (buffer_ != NULL && read_position_ + length_ <= capacity_) {
    void* result = realloc(buffer_, capacity);
    if (result == NULL) {
      return false;
    }
    capacity_ = capacity;
    buffer_ = result;
    return true;
  }

  void* buffer = malloc(capacity);
  if (buffer == NULL) {
    return false;
  }

  // Read does everything we want, but it will trounce length_.
  size_t length = length_;

  // Copy the data over to the new buffer.
  ReadUnchecked_Locked(buffer, length_, 0, NULL);

  // Adjust the accounting.
  length_ = length;
  read_position_ = 0;
  capacity_ = capacity;
  free(buffer_);
  buffer_ = buffer;
  return true;
}

size_t CircularBufferShell::GetMaxCapacity() const {
  base::AutoLock l(lock_);

  return max_capacity_;
}

void CircularBufferShell::IncreaseMaxCapacityTo(size_t new_max_capacity) {
  base::AutoLock l(lock_);

  DCHECK_GT(new_max_capacity, max_capacity_);
  if (new_max_capacity > max_capacity_) {
    max_capacity_ = new_max_capacity;
  }
}

}  // namespace base
