/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "java_lang_String.h"

#include "nativehelper/jni_macros.h"

#include "common_throws.h"
#include "jni_internal.h"
#include "mirror/array.h"
#include "mirror/object-inl.h"
#include "mirror/string.h"
#include "mirror/string-inl.h"
#include "scoped_fast_native_object_access-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "verify_object.h"

namespace art {

static jchar String_charAt(JNIEnv* env, jobject java_this, jint index) {
  ScopedFastNativeObjectAccess soa(env);
  return soa.Decode<mirror::String>(java_this)->CharAt(index);
}

static jint String_compareTo(JNIEnv* env, jobject java_this, jobject java_rhs) {
  ScopedFastNativeObjectAccess soa(env);
  if (UNLIKELY(java_rhs == nullptr)) {
    ThrowNullPointerException("rhs == null");
    return -1;
  } else {
    return soa.Decode<mirror::String>(java_this)->CompareTo(
        soa.Decode<mirror::String>(java_rhs).Ptr());
  }
}

static jstring String_concat(JNIEnv* env, jobject java_this, jobject java_string_arg) {
  ScopedFastNativeObjectAccess soa(env);
  if (UNLIKELY(java_string_arg == nullptr)) {
    ThrowNullPointerException("string arg == null");
    return nullptr;
  }
  StackHandleScope<2> hs(soa.Self());
  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
  Handle<mirror::String> string_arg(hs.NewHandle(soa.Decode<mirror::String>(java_string_arg)));
  int32_t length_this = string_this->GetLength();
  int32_t length_arg = string_arg->GetLength();
  if (length_arg > 0 && length_this > 0) {
    ObjPtr<mirror::String> result =
        mirror::String::AllocFromStrings(soa.Self(), string_this, string_arg);
    return soa.AddLocalReference<jstring>(result);
  }
  jobject string_original = (length_this == 0) ? java_string_arg : java_this;
  return reinterpret_cast<jstring>(string_original);
}

static jint String_fastIndexOf(JNIEnv* env, jobject java_this, jint ch, jint start) {
  ScopedFastNativeObjectAccess soa(env);
  // This method does not handle supplementary characters. They're dealt with in managed code.
  DCHECK_LE(ch, 0xffff);
  return soa.Decode<mirror::String>(java_this)->FastIndexOf(ch, start);
}

static jstring String_fastSubstring(JNIEnv* env, jobject java_this, jint start, jint length) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
  gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
  ObjPtr<mirror::String> result = mirror::String::AllocFromString<true>(soa.Self(),
                                                                        length,
                                                                        string_this,
                                                                        start,
                                                                        allocator_type);
  return soa.AddLocalReference<jstring>(result);
}

static void String_getCharsNoCheck(JNIEnv* env, jobject java_this, jint start, jint end,
                                   jcharArray buffer, jint index) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray>(buffer)));
  soa.Decode<mirror::String>(java_this)->GetChars(start, end, char_array, index);
}

static jstring String_intern(JNIEnv* env, jobject java_this) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::String> result = soa.Decode<mirror::String>(java_this)->Intern();
  return soa.AddLocalReference<jstring>(result);
}

static jstring String_doReplace(JNIEnv* env, jobject java_this, jchar old_c, jchar new_c) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::String> string = hs.NewHandle(soa.Decode<mirror::String>(java_this));
  ObjPtr<mirror::String> result = mirror::String::DoReplace(soa.Self(), string, old_c, new_c);
  return soa.AddLocalReference<jstring>(result);
}

static jcharArray String_toCharArray(JNIEnv* env, jobject java_this) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_this);
  return soa.AddLocalReference<jcharArray>(s->ToCharArray(soa.Self()));
}

static JNINativeMethod gMethods[] = {
  FAST_NATIVE_METHOD(String, charAt, "(I)C"),
  FAST_NATIVE_METHOD(String, compareTo, "(Ljava/lang/String;)I"),
  FAST_NATIVE_METHOD(String, concat, "(Ljava/lang/String;)Ljava/lang/String;"),
  FAST_NATIVE_METHOD(String, doReplace, "(CC)Ljava/lang/String;"),
  FAST_NATIVE_METHOD(String, fastIndexOf, "(II)I"),
  FAST_NATIVE_METHOD(String, fastSubstring, "(II)Ljava/lang/String;"),
  FAST_NATIVE_METHOD(String, getCharsNoCheck, "(II[CI)V"),
  FAST_NATIVE_METHOD(String, intern, "()Ljava/lang/String;"),
  FAST_NATIVE_METHOD(String, toCharArray, "()[C"),
};

void register_java_lang_String(JNIEnv* env) {
  REGISTER_NATIVE_METHODS("java/lang/String");
}

}  // namespace art
