// 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 "tonic/typed_data/dart_byte_data.h"

#include <cstring>

#include "tonic/logging/dart_error.h"

namespace tonic {

namespace {

// For large objects it is more efficient to use an external typed data object
// with a buffer allocated outside the Dart heap.
const int kExternalSizeThreshold = 1000;

void FreeFinalizer(void* isolate_callback_data, void* peer) {
  free(peer);
}

}  // anonymous namespace

Dart_Handle DartByteData::Create(const void* data, size_t length) {
  if (length < kExternalSizeThreshold) {
    auto handle = DartByteData{data, length}.dart_handle();
    // The destructor should release the typed data.
    return handle;
  } else {
    void* buf = ::malloc(length);
    TONIC_DCHECK(buf);
    ::memcpy(buf, data, length);
    return Dart_NewExternalTypedDataWithFinalizer(
        Dart_TypedData_kByteData, buf, length, buf, length, FreeFinalizer);
  }
}

DartByteData::DartByteData()
    : data_(nullptr), length_in_bytes_(0), dart_handle_(nullptr) {}

DartByteData::DartByteData(const void* data, size_t length)
    : data_(nullptr),
      length_in_bytes_(0),
      dart_handle_(Dart_NewTypedData(Dart_TypedData_kByteData, length)) {
  if (!Dart_IsError(dart_handle_)) {
    Dart_TypedData_Type type;
    auto acquire_result = Dart_TypedDataAcquireData(dart_handle_, &type, &data_,
                                                    &length_in_bytes_);

    if (!Dart_IsError(acquire_result)) {
      ::memcpy(data_, data, length_in_bytes_);
    }
  }
}

DartByteData::DartByteData(Dart_Handle list)
    : data_(nullptr), length_in_bytes_(0), dart_handle_(list) {
  if (Dart_IsNull(list))
    return;

  Dart_TypedData_Type type;
  Dart_TypedDataAcquireData(list, &type, &data_, &length_in_bytes_);
  TONIC_DCHECK(!LogIfError(list));
  if (type != Dart_TypedData_kByteData)
    Dart_ThrowException(ToDart("Non-genuine ByteData passed to engine."));
}

DartByteData::DartByteData(DartByteData&& other)
    : data_(other.data_),
      length_in_bytes_(other.length_in_bytes_),
      dart_handle_(other.dart_handle_) {
  other.data_ = nullptr;
  other.dart_handle_ = nullptr;
}

DartByteData::~DartByteData() {
  Release();
}

std::vector<char> DartByteData::Copy() const {
  const char* ptr = static_cast<const char*>(data_);
  return std::vector<char>(ptr, ptr + length_in_bytes_);
}

void DartByteData::Release() const {
  if (data_) {
    Dart_TypedDataReleaseData(dart_handle_);
    data_ = nullptr;
  }
}

DartByteData DartConverter<DartByteData>::FromArguments(
    Dart_NativeArguments args,
    int index,
    Dart_Handle& exception) {
  Dart_Handle data = Dart_GetNativeArgument(args, index);
  TONIC_DCHECK(!LogIfError(data));
  return DartByteData(data);
}

void DartConverter<DartByteData>::SetReturnValue(Dart_NativeArguments args,
                                                 DartByteData val) {
  Dart_SetReturnValue(args, val.dart_handle());
}

}  // namespace tonic
