android_util_StringBlock.cpp revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat/* //device/libs/android_runtime/android_util_StringBlock.cpp 2168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** 3168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** Copyright 2006, The Android Open Source Project 4168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** 5168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** Licensed under the Apache License, Version 2.0 (the "License"); 6168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** you may not use this file except in compliance with the License. 7168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** You may obtain a copy of the License at 8168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** 9168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** http://www.apache.org/licenses/LICENSE-2.0 10168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** 11168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** Unless required by applicable law or agreed to in writing, software 12168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** distributed under the License is distributed on an "AS IS" BASIS, 13168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** See the License for the specific language governing permissions and 15168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat** limitations under the License. 16168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat*/ 17168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 18168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#define LOG_TAG "StringBlock" 19168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 20168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include "jni.h" 21168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <utils/misc.h> 22168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <android_runtime/AndroidRuntime.h> 23168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <utils/Log.h> 24168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 25168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <utils/ResourceTypes.h> 26168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 27168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <stdio.h> 28168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 29168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatnamespace android { 30168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 31168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat// ---------------------------------------------------------------------------- 32168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 33168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatstatic void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL) 34168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat{ 35168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jclass npeClazz; 36168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 37168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat npeClazz = env->FindClass(exc); 38168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc); 39168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 40168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat env->ThrowNew(npeClazz, msg); 41168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 42168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 43168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatstatic jint android_content_StringBlock_nativeCreate(JNIEnv* env, jobject clazz, 44168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jbyteArray bArray, 45168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jint off, jint len) 46168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat{ 47168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (bArray == NULL) { 48168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat doThrow(env, "java/lang/NullPointerException"); 49168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return 0; 50168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 51168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 52168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jsize bLen = env->GetArrayLength(bArray); 53168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) { 54168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat doThrow(env, "java/lang/IndexOutOfBoundsException"); 55168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return 0; 56168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 57168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 58168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jbyte* b = env->GetByteArrayElements(bArray, NULL); 59168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat ResStringPool* osb = new ResStringPool(b+off, len, true); 60168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat env->ReleaseByteArrayElements(bArray, b, 0); 61168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 62168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (osb == NULL || osb->getError() != NO_ERROR) { 63168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat doThrow(env, "java/lang/IllegalArgumentException"); 64168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return 0; 65168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 66168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 67168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return (jint)osb; 68168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 69168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 70168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatstatic jint android_content_StringBlock_nativeGetSize(JNIEnv* env, jobject clazz, 71168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jint token) 72168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat{ 73168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat ResStringPool* osb = (ResStringPool*)token; 74168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (osb == NULL) { 75168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat doThrow(env, "java/lang/NullPointerException"); 76168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return 0; 77168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 78168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 79168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return osb->size(); 80168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 81168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 82168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatstatic jstring android_content_StringBlock_nativeGetString(JNIEnv* env, jobject clazz, 83168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jint token, jint idx) 84168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat{ 85168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat ResStringPool* osb = (ResStringPool*)token; 86168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (osb == NULL) { 87168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat doThrow(env, "java/lang/NullPointerException"); 88168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return 0; 89168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 90168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 91168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat size_t len; 92168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat const char16_t* str = osb->stringAt(idx, &len); 93168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (str == NULL) { 94168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat doThrow(env, "java/lang/IndexOutOfBoundsException"); 95168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return 0; 96168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 97168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 98168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return env->NewString((const jchar*)str, len); 99168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 100168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 101168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatstatic jintArray android_content_StringBlock_nativeGetStyle(JNIEnv* env, jobject clazz, 102168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jint token, jint idx) 103168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat{ 104168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat ResStringPool* osb = (ResStringPool*)token; 105168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (osb == NULL) { 106168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat doThrow(env, "java/lang/NullPointerException"); 107168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return NULL; 108168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 109168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 110168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat const ResStringPool_span* spans = osb->styleAt(idx); 111168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (spans == NULL) { 112168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return NULL; 113168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 114168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 115168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat const ResStringPool_span* pos = spans; 116168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int num = 0; 117168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat while (pos->name.index != ResStringPool_span::END) { 118168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat num++; 119168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat pos++; 120168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 121168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 122168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (num == 0) { 123168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return NULL; 124168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 125168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 126168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat jintArray array = env->NewIntArray((num*sizeof(ResStringPool_span))/sizeof(jint)); 127168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (array == NULL) { 128 doThrow(env, "java/lang/OutOfMemoryError"); 129 return NULL; 130 } 131 132 num = 0; 133 static const int numInts = sizeof(ResStringPool_span)/sizeof(jint); 134 while (spans->name.index != ResStringPool_span::END) { 135 env->SetIntArrayRegion(array, 136 num*numInts, numInts, 137 (jint*)spans); 138 spans++; 139 num++; 140 } 141 142 return array; 143} 144 145static jint android_content_StringBlock_nativeIndexOfString(JNIEnv* env, jobject clazz, 146 jint token, jstring str) 147{ 148 ResStringPool* osb = (ResStringPool*)token; 149 if (osb == NULL || str == NULL) { 150 doThrow(env, "java/lang/NullPointerException"); 151 return 0; 152 } 153 154 const char16_t* str16 = env->GetStringChars(str, NULL); 155 jsize strLen = env->GetStringLength(str); 156 157 ssize_t idx = osb->indexOfString(str16, strLen); 158 159 env->ReleaseStringChars(str, str16); 160 161 return idx; 162} 163 164static void android_content_StringBlock_nativeDestroy(JNIEnv* env, jobject clazz, 165 jint token) 166{ 167 ResStringPool* osb = (ResStringPool*)token; 168 if (osb == NULL) { 169 doThrow(env, "java/lang/NullPointerException"); 170 return; 171 } 172 173 delete osb; 174} 175 176// ---------------------------------------------------------------------------- 177 178/* 179 * JNI registration. 180 */ 181static JNINativeMethod gStringBlockMethods[] = { 182 /* name, signature, funcPtr */ 183 { "nativeCreate", "([BII)I", 184 (void*) android_content_StringBlock_nativeCreate }, 185 { "nativeGetSize", "(I)I", 186 (void*) android_content_StringBlock_nativeGetSize }, 187 { "nativeGetString", "(II)Ljava/lang/String;", 188 (void*) android_content_StringBlock_nativeGetString }, 189 { "nativeGetStyle", "(II)[I", 190 (void*) android_content_StringBlock_nativeGetStyle }, 191 { "nativeIndexOfString","(ILjava/lang/String;)I", 192 (void*) android_content_StringBlock_nativeIndexOfString }, 193 { "nativeDestroy", "(I)V", 194 (void*) android_content_StringBlock_nativeDestroy }, 195}; 196 197int register_android_content_StringBlock(JNIEnv* env) 198{ 199 return AndroidRuntime::registerNativeMethods(env, 200 "android/content/res/StringBlock", gStringBlockMethods, NELEM(gStringBlockMethods)); 201} 202 203}; // namespace android 204 205