// Copyright 2013 The Flutter 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 "flutter/fml/mapping.h"

#include <algorithm>
#include <sstream>

namespace fml {

// FileMapping

uint8_t* FileMapping::GetMutableMapping() {
  return mutable_mapping_;
}

std::unique_ptr<FileMapping> FileMapping::CreateReadOnly(
    const std::string& path) {
  return CreateReadOnly(OpenFile(path.c_str(), false, FilePermission::kRead),
                        "");
}

std::unique_ptr<FileMapping> FileMapping::CreateReadOnly(
    const fml::UniqueFD& base_fd,
    const std::string& sub_path) {
  if (sub_path.size() != 0) {
    return CreateReadOnly(
        OpenFile(base_fd, sub_path.c_str(), false, FilePermission::kRead), "");
  }

  auto mapping = std::make_unique<FileMapping>(
      base_fd, std::initializer_list<Protection>{Protection::kRead});

  if (!mapping->IsValid()) {
    return nullptr;
  }

  return mapping;
}

std::unique_ptr<FileMapping> FileMapping::CreateReadExecute(
    const std::string& path) {
  return CreateReadExecute(
      OpenFile(path.c_str(), false, FilePermission::kRead));
}

std::unique_ptr<FileMapping> FileMapping::CreateReadExecute(
    const fml::UniqueFD& base_fd,
    const std::string& sub_path) {
  if (sub_path.size() != 0) {
    return CreateReadExecute(
        OpenFile(base_fd, sub_path.c_str(), false, FilePermission::kRead), "");
  }

  auto mapping = std::make_unique<FileMapping>(
      base_fd, std::initializer_list<Protection>{Protection::kRead,
                                                 Protection::kExecute});

  if (!mapping->IsValid()) {
    return nullptr;
  }

  return mapping;
}

// Data Mapping

DataMapping::DataMapping(std::vector<uint8_t> data) : data_(std::move(data)) {}

DataMapping::DataMapping(const std::string& string)
    : data_(string.begin(), string.end()) {}

DataMapping::~DataMapping() = default;

size_t DataMapping::GetSize() const {
  return data_.size();
}

const uint8_t* DataMapping::GetMapping() const {
  return data_.data();
}

bool DataMapping::IsDontNeedSafe() const {
  return false;
}

// NonOwnedMapping
NonOwnedMapping::NonOwnedMapping(const uint8_t* data,
                                 size_t size,
                                 const ReleaseProc& release_proc,
                                 bool dontneed_safe)
    : data_(data),
      size_(size),
      release_proc_(release_proc),
      dontneed_safe_(dontneed_safe) {}

NonOwnedMapping::~NonOwnedMapping() {
  if (release_proc_) {
    release_proc_(data_, size_);
  }
}

size_t NonOwnedMapping::GetSize() const {
  return size_;
}

const uint8_t* NonOwnedMapping::GetMapping() const {
  return data_;
}

bool NonOwnedMapping::IsDontNeedSafe() const {
  return dontneed_safe_;
}

// MallocMapping
MallocMapping::MallocMapping() : data_(nullptr), size_(0) {}

MallocMapping::MallocMapping(uint8_t* data, size_t size)
    : data_(data), size_(size) {}

MallocMapping::MallocMapping(fml::MallocMapping&& mapping)
    : data_(mapping.data_), size_(mapping.size_) {
  mapping.data_ = nullptr;
  mapping.size_ = 0;
}

MallocMapping::~MallocMapping() {
  free(data_);
  data_ = nullptr;
}

MallocMapping MallocMapping::Copy(const void* begin, size_t length) {
  auto result =
      MallocMapping(reinterpret_cast<uint8_t*>(malloc(length)), length);
  FML_CHECK(result.GetMapping() != nullptr);
  memcpy(const_cast<uint8_t*>(result.GetMapping()), begin, length);
  return result;
}

size_t MallocMapping::GetSize() const {
  return size_;
}

const uint8_t* MallocMapping::GetMapping() const {
  return data_;
}

bool MallocMapping::IsDontNeedSafe() const {
  return false;
}

uint8_t* MallocMapping::Release() {
  uint8_t* result = data_;
  data_ = nullptr;
  size_ = 0;
  return result;
}

// Symbol Mapping

SymbolMapping::SymbolMapping(fml::RefPtr<fml::NativeLibrary> native_library,
                             const char* symbol_name)
    : native_library_(std::move(native_library)) {
  if (native_library_ && symbol_name != nullptr) {
    mapping_ = native_library_->ResolveSymbol(symbol_name);

    if (mapping_ == nullptr) {
      // Apparently, dart_bootstrap seems to account for the Mac behavior of
      // requiring the underscore prefixed symbol name on non-Mac platforms as
      // well. As a fallback, check the underscore prefixed variant of the
      // symbol name and allow callers to not have handle this on a per platform
      // toolchain quirk basis.

      std::stringstream underscore_symbol_name;
      underscore_symbol_name << "_" << symbol_name;
      mapping_ =
          native_library_->ResolveSymbol(underscore_symbol_name.str().c_str());
    }
  }
}

SymbolMapping::~SymbolMapping() = default;

size_t SymbolMapping::GetSize() const {
  return 0;
}

const uint8_t* SymbolMapping::GetMapping() const {
  return mapping_;
}

bool SymbolMapping::IsDontNeedSafe() const {
  return true;
}

}  // namespace fml
