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