Merge "Use JniDataUtils::outputCodePoints() to output code points"
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index a55b2da..9098b71 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -149,14 +149,16 @@
             it != attributeMap->end(); ++it) {
         // Output key
         jintArray keyCodePointArray = env->NewIntArray(it->first.size());
-        env->SetIntArrayRegion(
-                keyCodePointArray, 0 /* start */, it->first.size(), &it->first.at(0));
+        JniDataUtils::outputCodePoints(env, keyCodePointArray, 0 /* start */,
+                it->first.size(), it->first.data(), it->first.size(),
+                false /* needsNullTermination */);
         env->CallBooleanMethod(outAttributeKeys, addMethodId, keyCodePointArray);
         env->DeleteLocalRef(keyCodePointArray);
         // Output value
         jintArray valueCodePointArray = env->NewIntArray(it->second.size());
-        env->SetIntArrayRegion(
-                valueCodePointArray, 0 /* start */, it->second.size(), &it->second.at(0));
+        JniDataUtils::outputCodePoints(env, valueCodePointArray, 0 /* start */,
+                it->second.size(), it->second.data(), it->second.size(),
+                false /* needsNullTermination */);
         env->CallBooleanMethod(outAttributeValues, addMethodId, valueCodePointArray);
         env->DeleteLocalRef(valueCodePointArray);
     }
@@ -301,6 +303,9 @@
     memset(wordCodePoints, 0, sizeof(wordCodePoints));
     const int nextToken = dictionary->getNextWordAndNextToken(token, wordCodePoints);
     env->SetIntArrayRegion(outCodePoints, 0, outCodePointsLength, wordCodePoints);
+    JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
+            MAX_WORD_LENGTH /* maxLength */, wordCodePoints, outCodePointsLength,
+            false /* needsNullTermination */);
     return nextToken;
 }
 
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.cpp b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
index 95608dc..6f5f808 100644
--- a/native/jni/src/suggest/core/dictionary/property/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
@@ -16,14 +16,17 @@
 
 #include "suggest/core/dictionary/property/word_property.h"
 
+#include "utils/jni_data_utils.h"
+
 namespace latinime {
 
 void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
         jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outBigramTargets,
         jobject outBigramProbabilities, jobject outShortcutTargets,
         jobject outShortcutProbabilities) const {
-    env->SetIntArrayRegion(outCodePoints, 0 /* start */, mCodePoints.size(), &mCodePoints[0]);
-
+    JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
+            MAX_WORD_LENGTH /* maxLength */, mCodePoints.data(), mCodePoints.size(),
+            false /* needsNullTermination */);
     jboolean flags[] = {mUnigramProperty.isNotAWord(), mUnigramProperty.isBlacklisted(),
             !mBigrams.empty(), mUnigramProperty.hasShortcuts()};
     env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
@@ -41,8 +44,9 @@
     for (const auto &bigramProperty : mBigrams) {
         const std::vector<int> *const word1CodePoints = bigramProperty.getTargetCodePoints();
         jintArray bigramWord1CodePointArray = env->NewIntArray(word1CodePoints->size());
-        env->SetIntArrayRegion(bigramWord1CodePointArray, 0 /* start */,
-                word1CodePoints->size(), word1CodePoints->data());
+        JniDataUtils::outputCodePoints(env, bigramWord1CodePointArray, 0 /* start */,
+                word1CodePoints->size(), word1CodePoints->data(), word1CodePoints->size(),
+                false /* needsNullTermination */);
         env->CallBooleanMethod(outBigramTargets, addMethodId, bigramWord1CodePointArray);
         env->DeleteLocalRef(bigramWord1CodePointArray);
 
@@ -62,6 +66,9 @@
         jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
         env->SetIntArrayRegion(shortcutTargetCodePointArray, 0 /* start */,
                 targetCodePoints->size(), targetCodePoints->data());
+        JniDataUtils::outputCodePoints(env, shortcutTargetCodePointArray, 0 /* start */,
+                targetCodePoints->size(), targetCodePoints->data(), targetCodePoints->size(),
+                false /* needsNullTermination */);
         env->CallBooleanMethod(outShortcutTargets, addMethodId, shortcutTargetCodePointArray);
         env->DeleteLocalRef(shortcutTargetCodePointArray);
         jobject integerProbability = env->NewObject(integerClass, intToIntegerConstructorId,
diff --git a/native/jni/src/suggest/core/result/suggestion_results.cpp b/native/jni/src/suggest/core/result/suggestion_results.cpp
index 088a55f..6594a12 100644
--- a/native/jni/src/suggest/core/result/suggestion_results.cpp
+++ b/native/jni/src/suggest/core/result/suggestion_results.cpp
@@ -16,6 +16,8 @@
 
 #include "suggest/core/result/suggestion_results.h"
 
+#include "utils/jni_data_utils.h"
+
 namespace latinime {
 
 void SuggestionResults::outputSuggestions(JNIEnv *env, jintArray outSuggestionCount,
@@ -27,13 +29,9 @@
         const SuggestedWord &suggestedWord = mSuggestedWords.top();
         suggestedWord.getCodePointCount();
         const int start = outputIndex * MAX_WORD_LENGTH;
-        env->SetIntArrayRegion(outputCodePointsArray, start, suggestedWord.getCodePointCount(),
-                suggestedWord.getCodePoint());
-        if (suggestedWord.getCodePointCount() < MAX_WORD_LENGTH) {
-            const int terminal = 0;
-            env->SetIntArrayRegion(outputCodePointsArray, start + suggestedWord.getCodePointCount(),
-                    1 /* len */, &terminal);
-        }
+        JniDataUtils::outputCodePoints(env, outputCodePointsArray, start,
+                MAX_WORD_LENGTH /* maxLength */, suggestedWord.getCodePoint(),
+                suggestedWord.getCodePointCount(), true /* needsNullTermination */);
         const int score = suggestedWord.getScore();
         env->SetIntArrayRegion(outScoresArray, outputIndex, 1 /* len */, &score);
         const int indexToPartialCommit = suggestedWord.getIndexToPartialCommit();
diff --git a/native/jni/src/utils/jni_data_utils.h b/native/jni/src/utils/jni_data_utils.h
index 2ce02dc..0e393e3 100644
--- a/native/jni/src/utils/jni_data_utils.h
+++ b/native/jni/src/utils/jni_data_utils.h
@@ -65,6 +65,18 @@
         return attributeMap;
     }
 
+    static void outputCodePoints(JNIEnv *env, jintArray intArrayToOutputCodePoints, const int start,
+            const int maxLength, const int *const codePoints, const int codePointCount,
+            const bool needsNullTermination) {
+        const int outputCodePointCount = std::min(maxLength, codePointCount);
+        env->SetIntArrayRegion(intArrayToOutputCodePoints, start, outputCodePointCount, codePoints);
+        if (needsNullTermination && outputCodePointCount < maxLength) {
+            const int terminal = 0;
+            env->SetIntArrayRegion(intArrayToOutputCodePoints, start + outputCodePointCount,
+                    1 /* len */, &terminal);
+        }
+    }
+
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(JniDataUtils);
 };