java_lang_String.cc revision bf86d0438e9ef9c145ebcf16a2e74c4efaa2686a
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 17bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "jni_internal.h" 18bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "object.h" 19bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 20bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "JniConstants.h" // Last to avoid problems with LOG redefinition. 21bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 22bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#ifdef HAVE__MEMCMP16 23bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes// "count" is in 16-bit units. 24bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesextern "C" uint32_t __memcmp16(const uint16_t* s0, const uint16_t* s1, size_t count); 25bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#define MemCmp16 __memcmp16 26bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#else 27bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesuint32_t MemCmp16(const uint16_t* s0, const uint16_t* s1, size_t count) { 28bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes for (size_t i = 0; i < count; i++) { 29bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (s0[i] != s1[i]) { 30bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return static_cast<int32_t>(s0[i]) - static_cast<int32_t>(s1[i]); 31bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 32bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 33bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return 0; 34bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} 35bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#endif 36bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 37bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesnamespace art { 38bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 39bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesnamespace { 40bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 41bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesjint String_compareTo(JNIEnv* env, jobject javaThis, jobject javaRhs) { 42bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes String* lhs = Decode<String*>(env, javaThis); 43bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes String* rhs = Decode<String*>(env, javaRhs); 44bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 45bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (rhs == NULL) { 46bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "rhs == null"); 47bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return -1; 48bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 49bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 50bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // Quick test for comparison of a string with itself. 51bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (lhs == rhs) { 52bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return 0; 53bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 54bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 55bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // TODO: is this still true? 56bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // The annoying part here is that 0x00e9 - 0xffff != 0x00ea, 57bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // because the interpreter converts the characters to 32-bit integers 58bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // *without* sign extension before it subtracts them (which makes some 59bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // sense since "char" is unsigned). So what we get is the result of 60bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // 0x000000e9 - 0x0000ffff, which is 0xffff00ea. 61bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes int lhsCount = lhs->GetLength(); 62bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes int rhsCount = rhs->GetLength(); 63bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes int countDiff = lhsCount - rhsCount; 64bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes int minCount = (countDiff < 0) ? lhsCount : rhsCount; 65bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes const uint16_t* lhsChars = lhs->GetCharArray()->GetData() + lhs->GetOffset(); 66bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes const uint16_t* rhsChars = rhs->GetCharArray()->GetData() + rhs->GetOffset(); 67bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes int otherRes = MemCmp16(lhsChars, rhsChars, minCount); 68bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (otherRes != 0) { 69bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return otherRes; 70bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 71bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return countDiff; 72bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} 73bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 74bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesjboolean String_equals(JNIEnv* env, jobject javaThis, jobject javaRhs) { 75bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes String* lhs = Decode<String*>(env, javaThis); 76bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes String* rhs = Decode<String*>(env, javaRhs); 77bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 78bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // Quick test for comparison of a string with itself. 79bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (lhs == rhs) { 80bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return JNI_TRUE; 81bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 82bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 83bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // if (!(rhs instanceof String)) return false. 84bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (rhs == NULL || lhs->GetClass() != rhs->GetClass()) { 85bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return JNI_FALSE; 86bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 87bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 88bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // Quick length check. 89bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes int lhsCount = lhs->GetLength(); 90bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes int rhsCount = rhs->GetLength(); 91bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (lhsCount != rhsCount) { 92bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return JNI_FALSE; 93bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 94bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 95bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // You may, at this point, be tempted to pull out the hashCode fields 96bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // and compare them. If both fields have been initialized, and they 97bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // are not equal, we can return false immediately. 98bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // 99bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // However, the hashCode field is often not set. If it is set, 100bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // there's an excellent chance that the String is being used as a key 101bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // in a hashed data structure (e.g. HashMap). That data structure has 102bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // already made the comparison and determined that the hashes are equal, 103bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // making a check here redundant. 104bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // 105bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // It's not clear that checking the hashes will be a win in "typical" 106bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes // use cases. We err on the side of simplicity and ignore them. 107bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 108bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes const uint16_t* lhsChars = lhs->GetCharArray()->GetData() + lhs->GetOffset(); 109bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes const uint16_t* rhsChars = rhs->GetCharArray()->GetData() + rhs->GetOffset(); 110bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return (MemCmp16(lhsChars, rhsChars, lhsCount) == 0) ? JNI_TRUE : JNI_FALSE; 111bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} 112bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 113bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes/* 114bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * public int indexOf(int c, int start) 115bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * 116bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Scan forward through the string for a matching character. 117bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * The character must be <= 0xffff; this method does not handle supplementary 118bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * characters. 119bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * 120bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Determine the index of the first character matching "ch". The string 121bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * to search is described by "chars", "offset", and "count". 122bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * 123bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * The character must be <= 0xffff. Supplementary characters are handled in 124bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Java. 125bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * 126bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * The "start" parameter must be clamped to [0..count]. 127bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * 128bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Returns -1 if no match is found. 129bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes */ 130bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesjint String_fastIndexOf(JNIEnv* env, jobject javaThis, jint ch, jint start) { 131bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes String* s = Decode<String*>(env, javaThis); 132bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes const uint16_t* chars = s->GetCharArray()->GetData() + s->GetOffset(); 133bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 134bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (start < 0) { 135bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes start = 0; 136bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 137bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 138bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes /* 16-bit loop, slightly better on ARM */ 139bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes const uint16_t* ptr = chars + start; 140bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes const uint16_t* endPtr = chars + s->GetLength(); 141bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes while (ptr < endPtr) { 142bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (*ptr++ == ch) { 143bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return (ptr-1) - chars; 144bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 145bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 146bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 147bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return -1; 148bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} 149bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 150bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesjstring String_intern(JNIEnv* env, jobject javaThis) { 151bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes String* s = Decode<String*>(env, javaThis); 152bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes String* result = s->Intern(); 153bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes return AddLocalReference<jstring>(env, result); 154bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} 155bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 156bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott HughesJNINativeMethod gMethods[] = { 157bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes NATIVE_METHOD(String, compareTo, "(Ljava/lang/String;)I"), 158bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes NATIVE_METHOD(String, equals, "(Ljava/lang/Object;)Z"), 159bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes NATIVE_METHOD(String, fastIndexOf, "(II)I"), 160bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes NATIVE_METHOD(String, intern, "()Ljava/lang/String;"), 161bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}; 162bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 163bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} // namespace 164bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 165bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid register_java_lang_String(JNIEnv* env) { 166bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes jniRegisterNativeMethods(env, "java/lang/String", gMethods, NELEM(gMethods)); 167bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} 168bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 169bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} // namespace art 170