diff options
Diffstat (limited to 'jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp')
-rw-r--r-- | jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp b/jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp new file mode 100644 index 0000000..dcb63a1 --- /dev/null +++ b/jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <assert.h> +#include <cutils/log.h> +#include <jni.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> + +#include "../include/pinyinime.h" +#include "../include/sync.h" +#include "../include/userdict.h" + +#ifdef __cplusplus +extern "C" { +#endif + +using namespace ime_pinyin; + +#define RET_BUF_LEN 256 + +static char16 retbuf[RET_BUF_LEN]; +static char16 (*predict_buf)[kMaxPredictSize + 1] = NULL; +static size_t predict_len; + +static Sync sync_worker; + +static struct file_descriptor_offsets_t +{ + jclass mClass; + jfieldID mDescriptor; +} gFileDescriptorOffsets; + +JNIEXPORT jboolean JNICALL nativeImOpenDecoder(JNIEnv* env, jclass jclazz, + jbyteArray fn_sys_dict, + jbyteArray fn_usr_dict) { + jbyte *fsd = (*env).GetByteArrayElements(fn_sys_dict, 0); + jbyte *fud = (*env).GetByteArrayElements(fn_usr_dict, 0); + + jboolean jret = JNI_FALSE; + + if (im_open_decoder((const char*)fsd, (const char*)fud)) + jret = JNI_TRUE; + + (*env).ReleaseByteArrayElements(fn_sys_dict, fsd, 0); + (*env).ReleaseByteArrayElements(fn_usr_dict, fud, 0); + + return jret; +} + +JNIEXPORT jboolean JNICALL nativeImOpenDecoderFd(JNIEnv* env, jclass jclazz, + jobject fd_sys_dict, + jlong startoffset, + jlong length, + jbyteArray fn_usr_dict) { + jint fd = env->GetIntField(fd_sys_dict, gFileDescriptorOffsets.mDescriptor); + jbyte *fud = (*env).GetByteArrayElements(fn_usr_dict, 0); + + jboolean jret = JNI_FALSE; + + int newfd = dup(fd); + if (im_open_decoder_fd(newfd, startoffset, length, (const char*)fud)) + jret = JNI_TRUE; + + close(newfd); + + (*env).ReleaseByteArrayElements(fn_usr_dict, fud, 0); + + return jret; +} + +JNIEXPORT void JNICALL nativeImSetMaxLens(JNIEnv* env, jclass jclazz, + jint max_sps_len, + jint max_hzs_len) { + im_set_max_lens(static_cast<size_t>(max_sps_len), + static_cast<size_t>(max_hzs_len)); + return; +} + +JNIEXPORT jboolean JNICALL nativeImCloseDecoder(JNIEnv* env, jclass jclazz) { + im_close_decoder(); + return JNI_TRUE; +} + +JNIEXPORT jint JNICALL nativeImSearch(JNIEnv* env, jclass jclazz, + jbyteArray pybuf, jint pylen) { + jbyte *array_body = (*env).GetByteArrayElements(pybuf, 0); + + jint jret = 0; + if (NULL != array_body) { + jret = im_search((const char*)array_body, pylen); + } + + (*env).ReleaseByteArrayElements(pybuf, array_body, 0); + + return jret; +} + +JNIEXPORT jint JNICALL nativeImDelSearch(JNIEnv* env, jclass jclazz, jint pos, + jboolean is_pos_in_splid, + jboolean clear_fixed_this_step) { + return im_delsearch(pos, is_pos_in_splid, clear_fixed_this_step); +} + +JNIEXPORT void JNICALL nativeImResetSearch(JNIEnv* env, jclass jclazz) { + im_reset_search(); + return; +} + +JNIEXPORT jint JNICALL nativeImAddLetter(JNIEnv *env, jclass clazz, jbyte ch) { + return im_add_letter(ch); +} + +JNIEXPORT jstring JNICALL nativeImGetPyStr(JNIEnv* env, jclass jclazz, + jboolean decoded) { + size_t py_len; + const char *py = im_get_sps_str(&py_len); // py_len gets decoded length + assert(NULL != py); + if (!decoded) + py_len = strlen(py); + + const unsigned short *spl_start; + size_t len; + len = im_get_spl_start_pos(spl_start); + + size_t i; + for (i = 0; i < py_len; i++) + retbuf[i] = py[i]; + retbuf[i] = (char16)'\0'; + + jstring retstr = (*env).NewString((unsigned short*)retbuf, i); + return retstr; +} + +JNIEXPORT jint JNICALL nativeImGetPyStrLen(JNIEnv* env, jclass jclazz, + jboolean decoded) { + size_t py_len; + const char *py = im_get_sps_str(&py_len); // py_len gets decoded length + assert(NULL != py); + if (!decoded) + py_len = strlen(py); + return py_len; +} + +JNIEXPORT jintArray JNICALL nativeImGetSplStart(JNIEnv* env, jclass jclazz) { + const unsigned short *spl_start; + size_t len; + + // There will be len + 1 elements in the buffer when len > 0. + len = im_get_spl_start_pos(spl_start); + + jintArray arr = (*env).NewIntArray(len + 2); + jint *arr_body = (*env).GetIntArrayElements(arr, 0); + assert(NULL != arr_body); + arr_body[0] = len; // element 0 is used to store the length of buffer. + for (size_t i = 0; i <= len; i++) + arr_body[i + 1] = spl_start[i]; + + (*env).ReleaseIntArrayElements(arr, arr_body, 0); + + return arr; +} + +JNIEXPORT jstring JNICALL nativeImGetChoice(JNIEnv *env, jclass clazz, + jint candidateId) { + jstring retstr; + if(im_get_candidate(candidateId, retbuf, RET_BUF_LEN)) { + retstr = (*env).NewString(retbuf, utf16_strlen(retbuf)); + return retstr; + } else { + retstr = (*env).NewString((unsigned short*)retbuf, 0); + return retstr; + } +} + +JNIEXPORT jint JNICALL nativeImChoose(JNIEnv *env, jclass clazz, + jint choice_id) { + return im_choose(choice_id); +} + +JNIEXPORT jint JNICALL nativeImCancelLastChoice(JNIEnv *env, jclass clazz) { + return im_cancel_last_choice(); +} + +JNIEXPORT jint JNICALL nativeImGetFixedLen(JNIEnv *env, jclass clazz) { + return im_get_fixed_len(); +} + +JNIEXPORT jboolean JNICALL nativeImCancelInput(JNIEnv *env, jclass clazz) { + if (im_cancel_input()) + return JNI_TRUE; + + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL nativeImFlushCache(JNIEnv *env, jclass clazz) { + im_flush_cache(); + return JNI_TRUE; +} + +JNIEXPORT jint JNICALL nativeImGetPredictsNum(JNIEnv *env, jclass clazz, + jstring fixed_str) { + char16 *fixed_ptr = (char16*)(*env).GetStringChars(fixed_str, false); + size_t fixed_len = (size_t)(*env).GetStringLength(fixed_str); + + char16 fixed_buf[kMaxPredictSize + 1]; + + if (fixed_len > kMaxPredictSize) { + fixed_ptr += fixed_len - kMaxPredictSize; + fixed_len = kMaxPredictSize; + } + utf16_strncpy(fixed_buf, fixed_ptr, fixed_len); + fixed_buf[fixed_len] = (char16)'\0'; + + predict_len = im_get_predicts(fixed_buf, predict_buf); + + (*env).ReleaseStringChars(fixed_str, fixed_ptr); + + return predict_len; +} + +JNIEXPORT jstring JNICALL nativeImGetPredictItem(JNIEnv *env, jclass clazz, + jint predict_no) { + jstring retstr; + + if (predict_no < 0 || (size_t)predict_no >= predict_len) { + retstr = (*env).NewString((unsigned short*)predict_buf[0], 0); + } else { + retstr = (*env).NewString((unsigned short*)predict_buf[predict_no], + utf16_strlen(predict_buf[predict_no])); + } + return retstr; +} + +JNIEXPORT jboolean JNICALL nativeSyncBegin(JNIEnv *env, jclass clazz, + jbyteArray dict_file) { + jbyte *file_name = (*env).GetByteArrayElements(dict_file, 0); + + jboolean jret = JNI_FALSE; + if (true == sync_worker.begin((const char *)file_name)) + jret = JNI_TRUE; + + (*env).ReleaseByteArrayElements(dict_file, file_name, 0); + + return jret; +} + +JNIEXPORT jboolean JNICALL nativeSyncFinish(JNIEnv *env, jclass clazz) { + sync_worker.finish(); + return JNI_TRUE; +} + +JNIEXPORT jint JNICALL nativeSyncGetCapacity(JNIEnv *env, jclass clazz) { + return sync_worker.get_capacity(); +} + +JNIEXPORT jint JNICALL nativeSyncPutLemmas(JNIEnv *env, jclass clazz, + jstring tomerge) { + + char16 *ptr = (char16*)(*env).GetStringChars(tomerge, NULL); + int len = (size_t)(*env).GetStringLength(tomerge); + + int added = sync_worker.put_lemmas(ptr, len); + + (*env).ReleaseStringChars(tomerge, ptr); + + return added; +} + +JNIEXPORT jstring JNICALL nativeSyncGetLemmas(JNIEnv *env, jclass clazz) { + + int len = sync_worker.get_lemmas(retbuf, RET_BUF_LEN); + if (len == 0) + return NULL; + jstring retstr; + retstr = (*env).NewString((unsigned short*)retbuf, len); + return retstr; +} + +JNIEXPORT jint JNICALL nativeSyncGetLastCount(JNIEnv *env, jclass clazz) { + return sync_worker.get_last_got_count(); +} + +JNIEXPORT jint JNICALL nativeSyncGetTotalCount(JNIEnv *env, jclass clazz) { + return sync_worker.get_total_count(); +} + +JNIEXPORT jboolean JNICALL nativeSyncClearLastGot(JNIEnv *env, jclass clazz) { + sync_worker.clear_last_got(); + return JNI_TRUE; +} + +/** + * Table of methods associated with a single class. + */ +static JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + /* ------Functions for Pinyin-to-hanzi decoding begin--------->> */ + { "nativeImOpenDecoder", "([B[B)Z", + (void*) nativeImOpenDecoder }, + { "nativeImOpenDecoderFd", "(Ljava/io/FileDescriptor;JJ[B)Z", + (void*) nativeImOpenDecoderFd }, + { "nativeImSetMaxLens", "(II)V", + (void*) nativeImSetMaxLens }, + { "nativeImCloseDecoder", "()Z", + (void*) nativeImCloseDecoder }, + { "nativeImSearch", "([BI)I", + (void*) nativeImSearch }, + { "nativeImDelSearch", "(IZZ)I", + (void*) nativeImDelSearch }, + { "nativeImResetSearch", "()V", + (void*) nativeImResetSearch }, + { "nativeImAddLetter", "(B)I", + (void*) nativeImAddLetter }, + { "nativeImGetPyStr", "(Z)Ljava/lang/String;", + (void*) nativeImGetPyStr }, + { "nativeImGetPyStrLen", "(Z)I", + (void*) nativeImGetPyStrLen }, + { "nativeImGetSplStart", "()[I", + (void*) nativeImGetSplStart }, + { "nativeImGetChoice", "(I)Ljava/lang/String;", + (void*) nativeImGetChoice }, + { "nativeImChoose", "(I)I", + (void*) nativeImChoose }, + { "nativeImCancelLastChoice", "()I", + (void*) nativeImCancelLastChoice }, + { "nativeImGetFixedLen", "()I", + (void*) nativeImGetFixedLen }, + { "nativeImGetPredictsNum", "(Ljava/lang/String;)I", + (void*) nativeImGetPredictsNum }, + { "nativeImGetPredictItem", "(I)Ljava/lang/String;", + (void*) nativeImGetPredictItem }, + { "nativeImCancelInput", "()Z", + (void*) nativeImCancelInput }, + { "nativeImFlushCache", "()Z", + (void*) nativeImFlushCache }, + /* <<----Functions for Pinyin-to-hanzi decoding end------------- */ + + /* ------Functions for sync begin----------------------------->> */ + { "nativeSyncBegin", "([B)Z", + (void*) nativeSyncBegin }, + { "nativeSyncFinish", "()Z", + (void*) nativeSyncFinish }, + { "nativeSyncPutLemmas", "(Ljava/lang/String;)I", + (void*) nativeSyncPutLemmas }, + { "nativeSyncGetLemmas", "()Ljava/lang/String;", + (void*) nativeSyncGetLemmas }, + { "nativeSyncGetLastCount", "()I", + (void*) nativeSyncGetLastCount }, + { "nativeSyncGetTotalCount", "()I", + (void*) nativeSyncGetTotalCount }, + { "nativeSyncClearLastGot", "()Z", + (void*) nativeSyncClearLastGot }, + { "nativeSyncGetCapacity", "()I", + (void*) nativeSyncGetCapacity }, + /* <<----Functions for sync end--------------------------------- */ +}; + + +/* + * Register several native methods for one class. + */ +static int registerNativeMethods(JNIEnv* env, const char* className, + JNINativeMethod* gMethods, int numMethods) +{ + jclass clazz; + + clazz = (*env).FindClass(className); + if (clazz == NULL) { + return JNI_FALSE; + } + if ((*env).RegisterNatives(clazz, gMethods, numMethods) < 0) { + return JNI_FALSE; + } + + clazz = env->FindClass("java/io/FileDescriptor"); + LOG_FATAL_IF(clazz == NULL, "Unable to find Java class java.io.FileDescriptor"); + gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); + gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); + LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, + "Unable to find descriptor field in java.io.FileDescriptor"); + + return JNI_TRUE; +} + +/* + * Register native methods for all classes we know about. + */ +static int registerNatives(JNIEnv* env) +{ + if (!registerNativeMethods(env, + "com/android/inputmethod/pinyin/PinyinDecoderService", + gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) + return JNI_FALSE; + + return JNI_TRUE; +} + +/* + * Set some test stuff up. + * + * Returns the JNI version on success, -1 on failure. + */ +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = NULL; + jint result = -1; + + if ((*vm).GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { + goto bail; + } + assert(env != NULL); + + if (!registerNatives(env)) { + goto bail; + } + + /* success -- return valid version number */ + result = JNI_VERSION_1_4; + +bail: + return result; +} + +#ifdef __cplusplus +} +#endif |