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 "JNIHelp.h" 22 #include <utils/misc.h> 23 #include <android_runtime/AndroidRuntime.h> 24 #include <utils/Log.h> 25 26 #include <utils/ResourceTypes.h> 27 28 #include <stdio.h> 29 30 namespace android { 31 32 // ---------------------------------------------------------------------------- 33 34 static jint android_content_StringBlock_nativeCreate(JNIEnv* env, jobject clazz, 35 jbyteArray bArray, 36 jint off, jint len) 37 { 38 if (bArray == NULL) { 39 jniThrowNullPointerException(env, NULL); 40 return 0; 41 } 42 43 jsize bLen = env->GetArrayLength(bArray); 44 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) { 45 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 46 return 0; 47 } 48 49 jbyte* b = env->GetByteArrayElements(bArray, NULL); 50 ResStringPool* osb = new ResStringPool(b+off, len, true); 51 env->ReleaseByteArrayElements(bArray, b, 0); 52 53 if (osb == NULL || osb->getError() != NO_ERROR) { 54 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 55 return 0; 56 } 57 58 return (jint)osb; 59 } 60 61 static jint android_content_StringBlock_nativeGetSize(JNIEnv* env, jobject clazz, 62 jint token) 63 { 64 ResStringPool* osb = (ResStringPool*)token; 65 if (osb == NULL) { 66 jniThrowNullPointerException(env, NULL); 67 return 0; 68 } 69 70 return osb->size(); 71 } 72 73 static jstring android_content_StringBlock_nativeGetString(JNIEnv* env, jobject clazz, 74 jint token, jint idx) 75 { 76 ResStringPool* osb = (ResStringPool*)token; 77 if (osb == NULL) { 78 jniThrowNullPointerException(env, NULL); 79 return 0; 80 } 81 82 size_t len; 83 const char* str8 = osb->string8At(idx, &len); 84 if (str8 != NULL) { 85 return env->NewStringUTF(str8); 86 } 87 88 const char16_t* str = osb->stringAt(idx, &len); 89 if (str == NULL) { 90 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 91 return 0; 92 } 93 94 return env->NewString((const jchar*)str, len); 95 } 96 97 static jintArray android_content_StringBlock_nativeGetStyle(JNIEnv* env, jobject clazz, 98 jint token, jint idx) 99 { 100 ResStringPool* osb = (ResStringPool*)token; 101 if (osb == NULL) { 102 jniThrowNullPointerException(env, NULL); 103 return NULL; 104 } 105 106 const ResStringPool_span* spans = osb->styleAt(idx); 107 if (spans == NULL) { 108 return NULL; 109 } 110 111 const ResStringPool_span* pos = spans; 112 int num = 0; 113 while (pos->name.index != ResStringPool_span::END) { 114 num++; 115 pos++; 116 } 117 118 if (num == 0) { 119 return NULL; 120 } 121 122 jintArray array = env->NewIntArray((num*sizeof(ResStringPool_span))/sizeof(jint)); 123 if (array == NULL) { // NewIntArray already threw OutOfMemoryError. 124 return NULL; 125 } 126 127 num = 0; 128 static const int numInts = sizeof(ResStringPool_span)/sizeof(jint); 129 while (spans->name.index != ResStringPool_span::END) { 130 env->SetIntArrayRegion(array, 131 num*numInts, numInts, 132 (jint*)spans); 133 spans++; 134 num++; 135 } 136 137 return array; 138 } 139 140 static void android_content_StringBlock_nativeDestroy(JNIEnv* env, jobject clazz, 141 jint token) 142 { 143 ResStringPool* osb = (ResStringPool*)token; 144 if (osb == NULL) { 145 jniThrowNullPointerException(env, NULL); 146 return; 147 } 148 149 delete osb; 150 } 151 152 // ---------------------------------------------------------------------------- 153 154 /* 155 * JNI registration. 156 */ 157 static JNINativeMethod gStringBlockMethods[] = { 158 /* name, signature, funcPtr */ 159 { "nativeCreate", "([BII)I", 160 (void*) android_content_StringBlock_nativeCreate }, 161 { "nativeGetSize", "(I)I", 162 (void*) android_content_StringBlock_nativeGetSize }, 163 { "nativeGetString", "(II)Ljava/lang/String;", 164 (void*) android_content_StringBlock_nativeGetString }, 165 { "nativeGetStyle", "(II)[I", 166 (void*) android_content_StringBlock_nativeGetStyle }, 167 { "nativeDestroy", "(I)V", 168 (void*) android_content_StringBlock_nativeDestroy }, 169 }; 170 171 int register_android_content_StringBlock(JNIEnv* env) 172 { 173 return AndroidRuntime::registerNativeMethods(env, 174 "android/content/res/StringBlock", gStringBlockMethods, NELEM(gStringBlockMethods)); 175 } 176 177 }; // namespace android 178