Home | History | Annotate | Download | only in jni
      1 /*
      2 **
      3 ** Copyright 2009, 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 #include <stdio.h>
     19 #include <assert.h>
     20 #include <unistd.h>
     21 #include <fcntl.h>
     22 
     23 #include <jni.h>
     24 #include "dictionary.h"
     25 
     26 // ----------------------------------------------------------------------------
     27 
     28 using namespace latinime;
     29 
     30 //
     31 // helper function to throw an exception
     32 //
     33 static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data)
     34 {
     35     if (jclass cls = env->FindClass(ex)) {
     36         char msg[1000];
     37         sprintf(msg, fmt, data);
     38         env->ThrowNew(cls, msg);
     39         env->DeleteLocalRef(cls);
     40     }
     41 }
     42 
     43 static jint latinime_BinaryDictionary_open
     44         (JNIEnv *env, jobject object, jobject dictDirectBuffer,
     45          jint typedLetterMultiplier, jint fullWordMultiplier)
     46 {
     47     void *dict = env->GetDirectBufferAddress(dictDirectBuffer);
     48     if (dict == NULL) {
     49         fprintf(stderr, "DICT: Dictionary buffer is null\n");
     50         return 0;
     51     }
     52     Dictionary *dictionary = new Dictionary(dict, typedLetterMultiplier, fullWordMultiplier);
     53     return (jint) dictionary;
     54 }
     55 
     56 static int latinime_BinaryDictionary_getSuggestions(
     57         JNIEnv *env, jobject object, jint dict, jintArray inputArray, jint arraySize,
     58         jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxWords,
     59         jint maxAlternatives, jint skipPos, jintArray nextLettersArray, jint nextLettersSize)
     60 {
     61     Dictionary *dictionary = (Dictionary*) dict;
     62     if (dictionary == NULL) return 0;
     63 
     64     int *frequencies = env->GetIntArrayElements(frequencyArray, NULL);
     65     int *inputCodes = env->GetIntArrayElements(inputArray, NULL);
     66     jchar *outputChars = env->GetCharArrayElements(outputArray, NULL);
     67     int *nextLetters = nextLettersArray != NULL ? env->GetIntArrayElements(nextLettersArray, NULL)
     68             : NULL;
     69 
     70     int count = dictionary->getSuggestions(inputCodes, arraySize, (unsigned short*) outputChars,
     71             frequencies, maxWordLength, maxWords, maxAlternatives, skipPos, nextLetters,
     72             nextLettersSize);
     73 
     74     env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
     75     env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
     76     env->ReleaseCharArrayElements(outputArray, outputChars, 0);
     77     if (nextLetters) {
     78         env->ReleaseIntArrayElements(nextLettersArray, nextLetters, 0);
     79     }
     80 
     81     return count;
     82 }
     83 
     84 static int latinime_BinaryDictionary_getBigrams
     85         (JNIEnv *env, jobject object, jint dict, jcharArray prevWordArray, jint prevWordLength,
     86          jintArray inputArray, jint inputArraySize, jcharArray outputArray,
     87          jintArray frequencyArray, jint maxWordLength, jint maxBigrams, jint maxAlternatives)
     88 {
     89     Dictionary *dictionary = (Dictionary*) dict;
     90     if (dictionary == NULL) return 0;
     91 
     92     jchar *prevWord = env->GetCharArrayElements(prevWordArray, NULL);
     93     int *inputCodes = env->GetIntArrayElements(inputArray, NULL);
     94     jchar *outputChars = env->GetCharArrayElements(outputArray, NULL);
     95     int *frequencies = env->GetIntArrayElements(frequencyArray, NULL);
     96 
     97     int count = dictionary->getBigrams((unsigned short*) prevWord, prevWordLength, inputCodes,
     98             inputArraySize, (unsigned short*) outputChars, frequencies, maxWordLength, maxBigrams,
     99             maxAlternatives);
    100 
    101     env->ReleaseCharArrayElements(prevWordArray, prevWord, JNI_ABORT);
    102     env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
    103     env->ReleaseCharArrayElements(outputArray, outputChars, 0);
    104     env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
    105 
    106     return count;
    107 }
    108 
    109 
    110 static jboolean latinime_BinaryDictionary_isValidWord
    111         (JNIEnv *env, jobject object, jint dict, jcharArray wordArray, jint wordLength)
    112 {
    113     Dictionary *dictionary = (Dictionary*) dict;
    114     if (dictionary == NULL) return (jboolean) false;
    115 
    116     jchar *word = env->GetCharArrayElements(wordArray, NULL);
    117     jboolean result = dictionary->isValidWord((unsigned short*) word, wordLength);
    118     env->ReleaseCharArrayElements(wordArray, word, JNI_ABORT);
    119 
    120     return result;
    121 }
    122 
    123 static void latinime_BinaryDictionary_close
    124         (JNIEnv *env, jobject object, jint dict)
    125 {
    126     Dictionary *dictionary = (Dictionary*) dict;
    127     delete (Dictionary*) dict;
    128 }
    129 
    130 // ----------------------------------------------------------------------------
    131 
    132 static JNINativeMethod gMethods[] = {
    133     {"openNative",           "(Ljava/nio/ByteBuffer;II)I",
    134                                           (void*)latinime_BinaryDictionary_open},
    135     {"closeNative",          "(I)V",            (void*)latinime_BinaryDictionary_close},
    136     {"getSuggestionsNative", "(I[II[C[IIIII[II)I",  (void*)latinime_BinaryDictionary_getSuggestions},
    137     {"isValidWordNative",    "(I[CI)Z",         (void*)latinime_BinaryDictionary_isValidWord},
    138     {"getBigramsNative",    "(I[CI[II[C[IIII)I",         (void*)latinime_BinaryDictionary_getBigrams}
    139 };
    140 
    141 static int registerNativeMethods(JNIEnv* env, const char* className,
    142     JNINativeMethod* gMethods, int numMethods)
    143 {
    144     jclass clazz;
    145 
    146     clazz = env->FindClass(className);
    147     if (clazz == NULL) {
    148         fprintf(stderr,
    149             "Native registration unable to find class '%s'\n", className);
    150         return JNI_FALSE;
    151     }
    152     if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
    153         fprintf(stderr, "RegisterNatives failed for '%s'\n", className);
    154         return JNI_FALSE;
    155     }
    156 
    157     return JNI_TRUE;
    158 }
    159 
    160 static int registerNatives(JNIEnv *env)
    161 {
    162     const char* const kClassPathName = "com/android/inputmethod/latin/BinaryDictionary";
    163     return registerNativeMethods(env,
    164             kClassPathName, gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
    165 }
    166 
    167 /*
    168  * Returns the JNI version on success, -1 on failure.
    169  */
    170 jint JNI_OnLoad(JavaVM* vm, void* reserved)
    171 {
    172     JNIEnv* env = NULL;
    173     jint result = -1;
    174 
    175     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    176         fprintf(stderr, "ERROR: GetEnv failed\n");
    177         goto bail;
    178     }
    179     assert(env != NULL);
    180 
    181     if (!registerNatives(env)) {
    182         fprintf(stderr, "ERROR: BinaryDictionary native registration failed\n");
    183         goto bail;
    184     }
    185 
    186     /* success -- return valid version number */
    187     result = JNI_VERSION_1_4;
    188 
    189 bail:
    190     return result;
    191 }
    192