// Copyright (c) 2011, 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/bootstrap_natives.h"

#include "include/dart_api.h"
#include "vm/exceptions.h"
#include "vm/dart_api_impl.h"
#include "vm/isolate.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/symbols.h"
#include "vm/unicode.h"

namespace dart {

DEFINE_NATIVE_ENTRY(String_fromEnvironment, 3) {
  GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
  GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(2));
  // Call the embedder to supply us with the environment.
  Api::Scope api_scope(isolate);
  Dart_EnvironmentCallback callback = isolate->environment_callback();
  if (callback != NULL) {
    Dart_Handle result = callback(Api::NewHandle(isolate, name.raw()));
    if (Dart_IsString(result)) {
      const Object& value =
          Object::Handle(isolate, Api::UnwrapHandle(result));
      return Symbols::New(String::Cast(value));
    } else if (Dart_IsError(result)) {
      const Object& error =
          Object::Handle(isolate, Api::UnwrapHandle(result));
      Exceptions::ThrowArgumentError(
          String::Handle(
              String::New(Error::Cast(error).ToErrorCString())));
    } else if (!Dart_IsNull(result)) {
      Exceptions::ThrowArgumentError(
          String::Handle(String::New("Illegal environment value")));
    }
  }
  return default_value.raw();
}


DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, list, arguments->NativeArgAt(0));
  if (!list.IsGrowableObjectArray() && !list.IsArray()) {
    Exceptions::ThrowArgumentError(list);
  }

  Array& a = Array::Handle();
  intptr_t array_len;
  if (list.IsGrowableObjectArray()) {
    const GrowableObjectArray& growableArray = GrowableObjectArray::Cast(list);
    a ^= growableArray.data();
    array_len = growableArray.Length();
  } else {
    a ^= Array::Cast(list).raw();
    array_len = a.Length();
  }

  Zone* zone = isolate->current_zone();

  // Unbox the array and determine the maximum element width.
  bool is_one_byte_string = true;
  intptr_t utf16_len = array_len;
  int32_t* utf32_array = zone->Alloc<int32_t>(array_len);
  Instance& index_object = Instance::Handle(isolate);
  for (intptr_t i = 0; i < array_len; i++) {
    index_object ^= a.At(i);
    if (!index_object.IsSmi()) {
      Exceptions::ThrowArgumentError(index_object);
    }
    intptr_t value = Smi::Cast(index_object).Value();
    if (Utf::IsOutOfRange(value)) {
      Exceptions::ThrowByType(Exceptions::kArgument, Object::empty_array());
      UNREACHABLE();
    }
    // Now it is safe to cast the value.
    int32_t value32 = static_cast<int32_t>(value);
    if (!Utf::IsLatin1(value32)) {
      is_one_byte_string = false;
      if (Utf::IsSupplementary(value32)) {
        utf16_len += 1;
      }
    }
    utf32_array[i] = value32;
  }
  if (is_one_byte_string) {
    return OneByteString::New(utf32_array, array_len, Heap::kNew);
  }
  return TwoByteString::New(utf16_len, utf32_array, array_len, Heap::kNew);
}


DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));

  intptr_t start = start_obj.Value();
  intptr_t end = end_obj.Value();
  return String::SubString(receiver, start, (end - start));
}


DEFINE_NATIVE_ENTRY(OneByteString_substringUnchecked, 3) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  ASSERT(receiver.IsOneByteString());
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));

  const intptr_t start = start_obj.Value();
  const intptr_t end = end_obj.Value();
  return OneByteString::New(receiver, start, end - start, Heap::kNew);
}


// This is high-performance code.
DEFINE_NATIVE_ENTRY(OneByteString_splitWithCharCode, 2) {
  const String& receiver = String::CheckedHandle(isolate,
                                                 arguments->NativeArgAt(0));
  ASSERT(receiver.IsOneByteString());
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_split_code, arguments->NativeArgAt(1));
  const intptr_t len = receiver.Length();
  const intptr_t split_code = smi_split_code.Value();
  const GrowableObjectArray& result = GrowableObjectArray::Handle(
      isolate,
      GrowableObjectArray::New(16, Heap::kNew));
  String& str = String::Handle(isolate);
  intptr_t start = 0;
  intptr_t i = 0;
  for (; i < len; i++) {
    if (split_code == OneByteString::CharAt(receiver, i)) {
      str = OneByteString::SubStringUnchecked(receiver,
                                              start,
                                              (i - start),
                                              Heap::kNew);
      result.Add(str);
      start = i + 1;
    }
  }
  str = OneByteString::SubStringUnchecked(receiver,
                                          start,
                                          (i - start),
                                          Heap::kNew);
  result.Add(str);
  return result.raw();
}


DEFINE_NATIVE_ENTRY(OneByteString_allocate, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length_obj, arguments->NativeArgAt(0));
  return OneByteString::New(length_obj.Value(), Heap::kNew);
}


DEFINE_NATIVE_ENTRY(OneByteString_allocateFromOneByteList, 1) {
  Instance& list = Instance::CheckedHandle(arguments->NativeArgAt(0));
  if (list.IsTypedData()) {
    const TypedData& array = TypedData::Cast(list);
    intptr_t length = array.LengthInBytes();
    return OneByteString::New(array, 0, length);
  } else if (list.IsExternalTypedData()) {
    const ExternalTypedData& array = ExternalTypedData::Cast(list);
    intptr_t length = array.LengthInBytes();
    return OneByteString::New(array, 0, length);
  } else if (RawObject::IsTypedDataViewClassId(list.GetClassId())) {
    const Instance& view = Instance::Cast(list);
    intptr_t length = Smi::Value(TypedDataView::Length(view));
    const Instance& data_obj = Instance::Handle(TypedDataView::Data(view));
    intptr_t data_offset = Smi::Value(TypedDataView::OffsetInBytes(view));
    if (data_obj.IsTypedData()) {
      const TypedData& array = TypedData::Cast(data_obj);
      return OneByteString::New(array, data_offset, length);
    } else if (data_obj.IsExternalTypedData()) {
      const ExternalTypedData& array = ExternalTypedData::Cast(data_obj);
      return OneByteString::New(array, data_offset, length);
    }
  } else if (list.IsArray()) {
    const Array& array = Array::Cast(list);
    intptr_t length = array.Length();
    String& string = String::Handle(OneByteString::New(length, Heap::kNew));
    for (int i = 0; i < length; i++) {
      intptr_t value = Smi::Value(reinterpret_cast<RawSmi*>(array.At(i)));
      OneByteString::SetCharAt(string, i, value);
    }
    return string.raw();
  } else if (list.IsGrowableObjectArray()) {
    const GrowableObjectArray& array = GrowableObjectArray::Cast(list);
    intptr_t length = array.Length();
    String& string = String::Handle(OneByteString::New(length, Heap::kNew));
    for (int i = 0; i < length; i++) {
      intptr_t value = Smi::Value(reinterpret_cast<RawSmi*>(array.At(i)));
      OneByteString::SetCharAt(string, i, value);
    }
    return string.raw();
  }
  UNREACHABLE();
  return Object::null();
}


DEFINE_NATIVE_ENTRY(OneByteString_setAt, 3) {
  GET_NON_NULL_NATIVE_ARGUMENT(String, receiver, arguments->NativeArgAt(0));
  ASSERT(receiver.IsOneByteString());
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, index_obj, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, code_point_obj, arguments->NativeArgAt(2));
  ASSERT((0 <= code_point_obj.Value()) && (code_point_obj.Value() <= 0xFF));
  OneByteString::SetCharAt(receiver, index_obj.Value(), code_point_obj.Value());
  return Object::null();
}


DEFINE_NATIVE_ENTRY(ExternalOneByteString_getCid, 0) {
  return Smi::New(kExternalOneByteStringCid);
}


DEFINE_NATIVE_ENTRY(String_getHashCode, 1) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  intptr_t hash_val = receiver.Hash();
  ASSERT(hash_val > 0);
  ASSERT(Smi::IsValid(hash_val));
  return Smi::New(hash_val);
}


DEFINE_NATIVE_ENTRY(String_getLength, 1) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  return Smi::New(receiver.Length());
}


static int32_t StringValueAt(const String& str, const Integer& index) {
  if (index.IsSmi()) {
    const Smi& smi = Smi::Cast(index);
    intptr_t index = smi.Value();
    if ((index < 0) || (index >= str.Length())) {
      const Array& args = Array::Handle(Array::New(1));
      args.SetAt(0, smi);
      Exceptions::ThrowByType(Exceptions::kRange, args);
    }
    return str.CharAt(index);
  } else {
    // An index larger than Smi is always illegal.
    const Array& args = Array::Handle(Array::New(1));
    args.SetAt(0, index);
    Exceptions::ThrowByType(Exceptions::kRange, args);
    return 0;
  }
}


DEFINE_NATIVE_ENTRY(String_charAt, 2) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
  uint32_t value = StringValueAt(receiver, index);
  ASSERT(value <= 0x10FFFF);
  return Symbols::FromCharCode(value);
}


DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));

  int32_t value = StringValueAt(receiver, index);
  ASSERT(value >= 0);
  ASSERT(value <= 0xFFFF);
  return Smi::New(value);
}


DEFINE_NATIVE_ENTRY(String_concat, 2) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1));
  return String::Concat(receiver, b);
}


DEFINE_NATIVE_ENTRY(String_toLowerCase, 1) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  ASSERT(!receiver.IsNull());
  return String::ToLowerCase(receiver);
}


DEFINE_NATIVE_ENTRY(String_toUpperCase, 1) {
  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
  ASSERT(!receiver.IsNull());
  return String::ToUpperCase(receiver);
}


DEFINE_NATIVE_ENTRY(String_concatRange, 3) {
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, argument, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, end, arguments->NativeArgAt(2));
  const intptr_t start_ix = start.Value();
  const intptr_t end_ix = end.Value();
  if (start_ix < 0) {
    Exceptions::ThrowArgumentError(start);
  }
  Array& strings = Array::Handle();
  intptr_t length = -1;
  if (argument.IsArray()) {
    strings ^= argument.raw();
    length = strings.Length();
  } else if (argument.IsGrowableObjectArray()) {
    const GrowableObjectArray& g_array = GrowableObjectArray::Cast(argument);
    strings = g_array.data();
    length =  g_array.Length();
  } else {
    Exceptions::ThrowArgumentError(argument);
  }
  if (end_ix > length) {
    Exceptions::ThrowArgumentError(end);
  }
#if defined(DEBUG)
  // Check that the array contains strings.
  Instance& elem = Instance::Handle();
  for (intptr_t i = start_ix; i < end_ix; i++) {
    elem ^= strings.At(i);
    ASSERT(elem.IsString());
  }
#endif
  return String::ConcatAllRange(strings, start_ix, end_ix, Heap::kNew);
}


DEFINE_NATIVE_ENTRY(StringBuffer_createStringFromUint16Array, 3) {
  GET_NON_NULL_NATIVE_ARGUMENT(TypedData, codeUnits, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Bool, isLatin1, arguments->NativeArgAt(2));
  intptr_t array_length = codeUnits.Length();
  intptr_t length_value = length.Value();
  if (length_value < 0 || length_value > array_length) {
    const Array& args = Array::Handle(Array::New(1));
    args.SetAt(0, length);
    Exceptions::ThrowByType(Exceptions::kRange, args);
  }
  const String& result = isLatin1.value()
      ? String::Handle(OneByteString::New(length_value, Heap::kNew))
      : String::Handle(TwoByteString::New(length_value, Heap::kNew));
  NoGCScope no_gc;

  uint16_t* data_position = reinterpret_cast<uint16_t*>(codeUnits.DataAddr(0));
  String::Copy(result, 0, data_position, length_value);
  return result.raw();
}

}  // namespace dart
