1 /* //device/libs/android_runtime/android_util_StringBlock.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "StringBlock" 19 20 #include "jni.h" 21 #include <utils/misc.h> 22 #include <android_runtime/AndroidRuntime.h> 23 #include <utils/Log.h> 24 25 #include <utils/ResourceTypes.h> 26 27 #include <stdio.h> 28 29 namespace android { 30 31 // ---------------------------------------------------------------------------- 32 33 static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL) 34 { 35 jclass npeClazz; 36 37 npeClazz = env->FindClass(exc); 38 LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc); 39 40 env->ThrowNew(npeClazz, msg); 41 } 42 43 static jint android_content_StringBlock_nativeCreate(JNIEnv* env, jobject clazz, 44 jbyteArray bArray, 45 jint off, jint len) 46 { 47 if (bArray == NULL) { 48 doThrow(env, "java/lang/NullPointerException"); 49 return 0; 50 } 51 52 jsize bLen = env->GetArrayLength(bArray); 53 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) { 54 doThrow(env, "java/lang/IndexOutOfBoundsException"); 55 return 0; 56 } 57 58 jbyte* b = env->GetByteArrayElements(bArray, NULL); 59 ResStringPool* osb = new ResStringPool(b+off, len, true); 60 env->ReleaseByteArrayElements(bArray, b, 0); 61 62 if (osb == NULL || osb->getError() != NO_ERROR) { 63 doThrow(env, "java/lang/IllegalArgumentException"); 64 return 0; 65 } 66 67 return (jint)osb; 68 } 69 70 static jint android_content_StringBlock_nativeGetSize(JNIEnv* env, jobject clazz, 71 jint token) 72 { 73 ResStringPool* osb = (ResStringPool*)token; 74 if (osb == NULL) { 75 doThrow(env, "java/lang/NullPointerException"); 76 return 0; 77 } 78 79 return osb->size(); 80 } 81 82 static jstring android_content_StringBlock_nativeGetString(JNIEnv* env, jobject clazz, 83 jint token, jint idx) 84 { 85 ResStringPool* osb = (ResStringPool*)token; 86 if (osb == NULL) { 87 doThrow(env, "java/lang/NullPointerException"); 88 return 0; 89 } 90 91 size_t len; 92 const char* str8 = osb->string8At(idx, &len); 93 if (str8 != NULL) { 94 return env->NewStringUTF(str8); 95 } 96 97 const char16_t* str = osb->stringAt(idx, &len); 98 if (str == NULL) { 99 doThrow(env, "java/lang/IndexOutOfBoundsException"); 100 return 0; 101 } 102 103 return env->NewString((const jchar*)str, len); 104 } 105 106 static jintArray android_content_StringBlock_nativeGetStyle(JNIEnv* env, jobject clazz, 107 jint token, jint idx) 108 { 109 ResStringPool* osb = (ResStringPool*)token; 110 if (osb == NULL) { 111 doThrow(env, "java/lang/NullPointerException"); 112 return NULL; 113 } 114 115 const ResStringPool_span* spans = osb->styleAt(idx); 116 if (spans == NULL) { 117 return NULL; 118 } 119 120 const ResStringPool_span* pos = spans; 121 int num = 0; 122 while (pos->name.index != ResStringPool_span::END) { 123 num++; 124 pos++; 125 } 126 127 if (num == 0) { 128 return NULL; 129 } 130 131 jintArray array = env->NewIntArray((num*sizeof(ResStringPool_span))/sizeof(jint)); 132 if (array == NULL) { 133 doThrow(env, "java/lang/OutOfMemoryError"); 134 return NULL; 135 } 136 137 num = 0; 138 static const int numInts = sizeof(ResStringPool_span)/sizeof(jint); 139 while (spans->name.index != ResStringPool_span::END) { 140 env->SetIntArrayRegion(array, 141 num*numInts, numInts, 142 (jint*)spans); 143 spans++; 144 num++; 145 } 146 147 return array; 148 } 149 150 static jint android_content_StringBlock_nativeIndexOfString(JNIEnv* env, jobject clazz, 151 jint token, jstring str) 152 { 153 ResStringPool* osb = (ResStringPool*)token; 154 if (osb == NULL || str == NULL) { 155 doThrow(env, "java/lang/NullPointerException"); 156 return 0; 157 } 158 159 const char16_t* str16 = env->GetStringChars(str, NULL); 160 jsize strLen = env->GetStringLength(str); 161 162 ssize_t idx = osb->indexOfString(str16, strLen); 163 164 env->ReleaseStringChars(str, str16); 165 166 return idx; 167 } 168 169 static void android_content_StringBlock_nativeDestroy(JNIEnv* env, jobject clazz, 170 jint token) 171 { 172 ResStringPool* osb = (ResStringPool*)token; 173 if (osb == NULL) { 174 doThrow(env, "java/lang/NullPointerException"); 175 return; 176 } 177 178 delete osb; 179 } 180 181 // ---------------------------------------------------------------------------- 182 183 /* 184 * JNI registration. 185 */ 186 static JNINativeMethod gStringBlockMethods[] = { 187 /* name, signature, funcPtr */ 188 { "nativeCreate", "([BII)I", 189 (void*) android_content_StringBlock_nativeCreate }, 190 { "nativeGetSize", "(I)I", 191 (void*) android_content_StringBlock_nativeGetSize }, 192 { "nativeGetString", "(II)Ljava/lang/String;", 193 (void*) android_content_StringBlock_nativeGetString }, 194 { "nativeGetStyle", "(II)[I", 195 (void*) android_content_StringBlock_nativeGetStyle }, 196 { "nativeIndexOfString","(ILjava/lang/String;)I", 197 (void*) android_content_StringBlock_nativeIndexOfString }, 198 { "nativeDestroy", "(I)V", 199 (void*) android_content_StringBlock_nativeDestroy }, 200 }; 201 202 int register_android_content_StringBlock(JNIEnv* env) 203 { 204 return AndroidRuntime::registerNativeMethods(env, 205 "android/content/res/StringBlock", gStringBlockMethods, NELEM(gStringBlockMethods)); 206 } 207 208 }; // namespace android 209 210