1bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes/*
2bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
4bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * you may not use this file except in compliance with the License.
6bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * You may obtain a copy of the License at
7bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
8bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
10bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Unless required by applicable law or agreed to in writing, software
11bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * See the License for the specific language governing permissions and
14bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * limitations under the License.
15bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes */
16bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "java_lang_String.h"
18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe
1962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
20bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "jni_internal.h"
21848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao#include "mirror/array.h"
22848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao#include "mirror/object-inl.h"
23848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao#include "mirror/string.h"
24b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
250795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_fast_native_object_access-inl.h"
260795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
2764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers#include "ScopedLocalRef.h"
2890b936ddda63139ff46a6755c3b83ad6e4ab4ac5Andreas Gampe#include "verify_object.h"
29bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
30bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesnamespace art {
31bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
32848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic jchar String_charAt(JNIEnv* env, jobject java_this, jint index) {
331eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  ScopedFastNativeObjectAccess soa(env);
340795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  return soa.Decode<mirror::String>(java_this)->CharAt(index);
35848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao}
36848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
37848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic jint String_compareTo(JNIEnv* env, jobject java_this, jobject java_rhs) {
38848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  ScopedFastNativeObjectAccess soa(env);
39848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (UNLIKELY(java_rhs == nullptr)) {
400aa50ce2fb75bfc2e815a0c33adf9b049561923bNicolas Geoffray    ThrowNullPointerException("rhs == null");
41bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return -1;
4264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else {
430795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier    return soa.Decode<mirror::String>(java_this)->CompareTo(
441cc62e4ea24828fdb3f3da0b8603f0b107d09a04Mathieu Chartier        soa.Decode<mirror::String>(java_rhs).Ptr());
45848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
46848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao}
47848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
48848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic jstring String_concat(JNIEnv* env, jobject java_this, jobject java_string_arg) {
49848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  ScopedFastNativeObjectAccess soa(env);
50848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (UNLIKELY(java_string_arg == nullptr)) {
51848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    ThrowNullPointerException("string arg == null");
52848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    return nullptr;
53848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
54848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  StackHandleScope<2> hs(soa.Self());
550795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
560795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  Handle<mirror::String> string_arg(hs.NewHandle(soa.Decode<mirror::String>(java_string_arg)));
57848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  int32_t length_this = string_this->GetLength();
58848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  int32_t length_arg = string_arg->GetLength();
59848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (length_arg > 0 && length_this > 0) {
60bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier    ObjPtr<mirror::String> result =
61bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier        mirror::String::AllocFromStrings(soa.Self(), string_this, string_arg);
62848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    return soa.AddLocalReference<jstring>(result);
63bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
64848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  jobject string_original = (length_this == 0) ? java_string_arg : java_this;
65848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  return reinterpret_cast<jstring>(string_original);
66bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
67bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
68529bfef6b3152fcf244e806ea6822ee96ff3eb4fElliott Hughesstatic jint String_fastIndexOf(JNIEnv* env, jobject java_this, jint ch, jint start) {
691eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  ScopedFastNativeObjectAccess soa(env);
70529bfef6b3152fcf244e806ea6822ee96ff3eb4fElliott Hughes  // This method does not handle supplementary characters. They're dealt with in managed code.
71529bfef6b3152fcf244e806ea6822ee96ff3eb4fElliott Hughes  DCHECK_LE(ch, 0xffff);
720795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  return soa.Decode<mirror::String>(java_this)->FastIndexOf(ch, start);
73848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao}
74bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
75848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic jstring String_fastSubstring(JNIEnv* env, jobject java_this, jint start, jint length) {
76848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  ScopedFastNativeObjectAccess soa(env);
77848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  StackHandleScope<1> hs(soa.Self());
780795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
79848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
80bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier  ObjPtr<mirror::String> result = mirror::String::AllocFromString<true>(soa.Self(),
81bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                                        length,
82bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                                        string_this,
83bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                                        start,
84bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                                        allocator_type);
85848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  return soa.AddLocalReference<jstring>(result);
86bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
87bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
88848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic void String_getCharsNoCheck(JNIEnv* env, jobject java_this, jint start, jint end,
89848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao                                   jcharArray buffer, jint index) {
901eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  ScopedFastNativeObjectAccess soa(env);
91848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  StackHandleScope<1> hs(soa.Self());
920795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray>(buffer)));
930795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  soa.Decode<mirror::String>(java_this)->GetChars(start, end, char_array, index);
94848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao}
95848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
96848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic jstring String_intern(JNIEnv* env, jobject java_this) {
97848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  ScopedFastNativeObjectAccess soa(env);
980795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  ObjPtr<mirror::String> result = soa.Decode<mirror::String>(java_this)->Intern();
9900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return soa.AddLocalReference<jstring>(result);
100bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
101bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
10292907f3f7af106a9eeb341caba17f3770203f7fbVladimir Markostatic jstring String_doReplace(JNIEnv* env, jobject java_this, jchar old_c, jchar new_c) {
103848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  ScopedFastNativeObjectAccess soa(env);
1049e57abacecc683f50dd6c9870a32ee075eaf86a8Vladimir Marko  StackHandleScope<1> hs(soa.Self());
1059e57abacecc683f50dd6c9870a32ee075eaf86a8Vladimir Marko  Handle<mirror::String> string = hs.NewHandle(soa.Decode<mirror::String>(java_this));
1069e57abacecc683f50dd6c9870a32ee075eaf86a8Vladimir Marko  ObjPtr<mirror::String> result = mirror::String::DoReplace(soa.Self(), string, old_c, new_c);
10792907f3f7af106a9eeb341caba17f3770203f7fbVladimir Marko  return soa.AddLocalReference<jstring>(result);
108848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao}
109848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
110848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic jcharArray String_toCharArray(JNIEnv* env, jobject java_this) {
111848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  ScopedFastNativeObjectAccess soa(env);
1120795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_this);
113848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  return soa.AddLocalReference<jcharArray>(s->ToCharArray(soa.Self()));
114848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao}
115848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
1160512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic JNINativeMethod gMethods[] = {
1173b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, charAt, "(I)C"),
1183b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, compareTo, "(Ljava/lang/String;)I"),
1193b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, concat, "(Ljava/lang/String;)Ljava/lang/String;"),
1203b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, doReplace, "(CC)Ljava/lang/String;"),
1213b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, fastIndexOf, "(II)I"),
1223b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, fastSubstring, "(II)Ljava/lang/String;"),
1233b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, getCharsNoCheck, "(II[CI)V"),
1243b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, intern, "()Ljava/lang/String;"),
1253b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(String, toCharArray, "()[C"),
126bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes};
127bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
128bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid register_java_lang_String(JNIEnv* env) {
129eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  REGISTER_NATIVE_METHODS("java/lang/String");
130bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
131bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
132bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}  // namespace art
133