// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <zircon/listnode.h>  // for containerof
#include <region-alloc/region-alloc.h>

extern "C" {

zx_status_t ralloc_create_pool(size_t max_memory, ralloc_pool_t** out_pool) {
  if (out_pool == nullptr)
    return ZX_ERR_INVALID_ARGS;

  auto pool = RegionAllocator::RegionPool::Create(max_memory);
  if (pool == nullptr)
    return ZX_ERR_NO_MEMORY;

  // Everything looks good.  Deliberately leak our reference out into the cold
  // cruel world of C.  I sure hope that it comes back some day...
  *out_pool = reinterpret_cast<ralloc_pool_t*>(fbl::ExportToRawPtr(&pool));

  return ZX_OK;
}

void ralloc_release_pool(ralloc_pool_t* pool) {
  ZX_DEBUG_ASSERT(pool != nullptr);

  // Reclaim our reference back from the land of C by turning the pointer
  // back into a RefPtr, then deliberately let it go out of scope, dropping
  // its reference and destructing the RegionPool if need be.
  auto release_me =
      fbl::ImportFromRawPtr(reinterpret_cast<RegionAllocator::RegionPool*>(pool));
}

zx_status_t ralloc_create_allocator(ralloc_allocator_t** out_allocator) {
  if (!out_allocator)
    return ZX_ERR_INVALID_ARGS;

  void* mem = ::malloc(sizeof(RegionAllocator));
  if (!mem)
    return ZX_ERR_NO_MEMORY;

  *out_allocator = reinterpret_cast<ralloc_allocator_t*>(new (mem) RegionAllocator());
  return ZX_OK;
}

zx_status_t ralloc_set_region_pool(ralloc_allocator_t* allocator, ralloc_pool* pool) {
  if (!allocator || !pool)
    return ZX_ERR_INVALID_ARGS;

  RegionAllocator& alloc = *(reinterpret_cast<RegionAllocator*>(allocator));

  // Turn our C-style pointer back into a RefPtr<> without adding a reference,
  // then use it to call the RegionAllocator::SetRegionPool method.  Finally,
  // deliberately leak the reference again so we are not accidentally removing
  // the unmanaged reference held by our C user.
  auto pool_ref =
      fbl::ImportFromRawPtr(reinterpret_cast<RegionAllocator::RegionPool*>(pool));
  zx_status_t ret = alloc.SetRegionPool(pool_ref);
  __UNUSED auto leak = fbl::ExportToRawPtr(&pool_ref);

  return ret;
}

void ralloc_reset_allocator(ralloc_allocator_t* allocator) {
  ZX_DEBUG_ASSERT(allocator);
  reinterpret_cast<RegionAllocator*>(allocator)->Reset();
}

void ralloc_destroy_allocator(ralloc_allocator_t* allocator) {
  ZX_DEBUG_ASSERT(allocator);

  RegionAllocator* alloc = reinterpret_cast<RegionAllocator*>(allocator);
  alloc->~RegionAllocator();
  ::free(alloc);
}

zx_status_t ralloc_add_region(ralloc_allocator_t* allocator, const ralloc_region_t* region,
                              bool allow_overlap) {
  if (!allocator || !region)
    return ZX_ERR_INVALID_ARGS;

  return reinterpret_cast<RegionAllocator*>(allocator)->AddRegion(*region, allow_overlap);
}

zx_status_t ralloc_sub_region(ralloc_allocator_t* allocator, const ralloc_region_t* region,
                              bool allow_incomplete) {
  if (!allocator || !region)
    return ZX_ERR_INVALID_ARGS;

  return reinterpret_cast<RegionAllocator*>(allocator)->SubtractRegion(*region, allow_incomplete);
}

zx_status_t ralloc_get_sized_region_ex(ralloc_allocator_t* allocator, uint64_t size,
                                       uint64_t alignment, const ralloc_region_t** out_region) {
  if (!allocator || !out_region)
    return ZX_ERR_INVALID_ARGS;

  RegionAllocator::Region::UPtr managed_region;
  RegionAllocator& alloc = *(reinterpret_cast<RegionAllocator*>(allocator));
  zx_status_t result = alloc.GetRegion(size, alignment, managed_region);

  if (result == ZX_OK) {
    // Everything looks good.  Detach the managed_region our unique_ptr<>
    // and send the unmanaged pointer to the inner ralloc_region_t back
    // to the caller.
    ZX_DEBUG_ASSERT(managed_region != nullptr);
    const RegionAllocator::Region* raw_region = managed_region.release();
    *out_region = static_cast<const ralloc_region_t*>(raw_region);
  } else {
    ZX_DEBUG_ASSERT(managed_region == nullptr);
    *out_region = nullptr;
  }

  return result;
}

zx_status_t ralloc_get_specific_region_ex(ralloc_allocator_t* allocator,
                                          const ralloc_region_t* requested_region,
                                          const ralloc_region_t** out_region) {
  if (!allocator || !requested_region || !out_region)
    return ZX_ERR_INVALID_ARGS;

  RegionAllocator::Region::UPtr managed_region;
  RegionAllocator& alloc = *(reinterpret_cast<RegionAllocator*>(allocator));
  zx_status_t result = alloc.GetRegion(*requested_region, managed_region);

  if (result == ZX_OK) {
    // Everything looks good.  Detach the managed_region our unique_ptr<>
    // and send the unmanaged pointer to the inner ralloc_region_t back
    // to the caller.
    ZX_DEBUG_ASSERT(managed_region != nullptr);
    const RegionAllocator::Region* raw_region = managed_region.release();
    *out_region = static_cast<const ralloc_region_t*>(raw_region);
  } else {
    ZX_DEBUG_ASSERT(managed_region == nullptr);
    *out_region = nullptr;
  }

  return result;
}

size_t ralloc_get_allocated_region_count(const ralloc_allocator_t* allocator) {
  ZX_DEBUG_ASSERT(allocator != nullptr);
  const RegionAllocator& alloc = *(reinterpret_cast<const RegionAllocator*>(allocator));
  return alloc.AllocatedRegionCount();
}

size_t ralloc_get_available_region_count(const ralloc_allocator_t* allocator) {
  ZX_DEBUG_ASSERT(allocator != nullptr);
  const RegionAllocator& alloc = *(reinterpret_cast<const RegionAllocator*>(allocator));
  return alloc.AvailableRegionCount();
}

void ralloc_put_region(const ralloc_region_t* region) {
  ZX_DEBUG_ASSERT(region);

  // Reclaim our reference back from the land of C by turning the pointer
  // back into a unique_ptr, then deliberately let it go out of scope, destroying the
  // RegionAllocator::Region in the process..
  auto raw_region = static_cast<const RegionAllocator::Region*>(region);
  RegionAllocator::Region::UPtr release_me(raw_region);
}

zx_status_t ralloc_walk_allocated_regions(const ralloc_allocator_t* allocator, region_walk_cb cb,
                                          void* ctx) {
  ZX_DEBUG_ASSERT(allocator != nullptr);
  if (cb == NULL) {
    return ZX_ERR_INVALID_ARGS;
  }

  const RegionAllocator& alloc = *(reinterpret_cast<const RegionAllocator*>(allocator));
  alloc.WalkAllocatedRegions([cb, ctx](const ralloc_region_t* r) -> bool { return cb(r, ctx); });

  return ZX_OK;
}

}  // extern "C"
