summaryrefslogtreecommitdiff
path: root/jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp')
-rw-r--r--jni/android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp441
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