Home | History | Annotate | Download | only in jni
      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