Implement latinime_BinaryDictionary_createOnMemory().

Bug: 14166482
Change-Id: If7ec3345ab34edcd6bc5cef9e72580ced894a0e3
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index b2946da..9016cae 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -51,7 +51,7 @@
     env->GetStringUTFRegion(sourceDir, 0, env->GetStringLength(sourceDir), sourceDirChars);
     sourceDirChars[sourceDirUtf8Length] = '\0';
     DictionaryStructureWithBufferPolicy::StructurePolicyPtr dictionaryStructureWithBufferPolicy(
-            DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy(
+            DictionaryStructureWithBufferPolicyFactory::newPolicyForExistingDictFile(
                     sourceDirChars, static_cast<int>(dictOffset), static_cast<int>(dictSize),
                     isUpdatable == JNI_TRUE));
     if (!dictionaryStructureWithBufferPolicy) {
@@ -68,8 +68,29 @@
 static jlong latinime_BinaryDictionary_createOnMemory(JNIEnv *env, jclass clazz,
         jlong formatVersion, jstring locale, jobjectArray attributeKeyStringArray,
         jobjectArray attributeValueStringArray) {
-    // TODO: Implement.
-    return 0;
+    const jsize localeUtf8Length = env->GetStringUTFLength(locale);
+    char localeChars[localeUtf8Length + 1];
+    env->GetStringUTFRegion(locale, 0, env->GetStringLength(locale), localeChars);
+    localeChars[localeUtf8Length] = '\0';
+    std::vector<int> localeCodePoints;
+    HeaderReadWriteUtils::insertCharactersIntoVector(localeChars, &localeCodePoints);
+    const int keyCount = env->GetArrayLength(attributeKeyStringArray);
+    const int valueCount = env->GetArrayLength(attributeValueStringArray);
+    if (keyCount != valueCount) {
+        return false;
+    }
+    DictionaryHeaderStructurePolicy::AttributeMap attributeMap =
+            JniDataUtils::constructAttributeMap(env, attributeKeyStringArray,
+                    attributeValueStringArray);
+    DictionaryStructureWithBufferPolicy::StructurePolicyPtr dictionaryStructureWithBufferPolicy =
+            DictionaryStructureWithBufferPolicyFactory::newPolicyForOnMemoryDict(
+                    formatVersion, localeCodePoints, &attributeMap);
+    if (!dictionaryStructureWithBufferPolicy) {
+        return 0;
+    }
+    Dictionary *const dictionary =
+            new Dictionary(env, std::move(dictionaryStructureWithBufferPolicy));
+    return reinterpret_cast<jlong>(dictionary);
 }
 
 static void latinime_BinaryDictionary_flush(JNIEnv *env, jclass clazz, jlong dict,
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
index 9ceea5b..0a34b78 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
@@ -36,9 +36,14 @@
     char filePathChars[filePathUtf8Length + 1];
     env->GetStringUTFRegion(filePath, 0, env->GetStringLength(filePath), filePathChars);
     filePathChars[filePathUtf8Length] = '\0';
-    jsize localeLength = env->GetStringLength(locale);
-    jchar localeCodePoints[localeLength];
-    env->GetStringRegion(locale, 0, localeLength, localeCodePoints);
+
+    const jsize localeUtf8Length = env->GetStringUTFLength(locale);
+    char localeChars[localeUtf8Length + 1];
+    env->GetStringUTFRegion(locale, 0, env->GetStringLength(locale), localeChars);
+    localeChars[localeUtf8Length] = '\0';
+    std::vector<int> localeCodePoints;
+    HeaderReadWriteUtils::insertCharactersIntoVector(localeChars, &localeCodePoints);
+
     const int keyCount = env->GetArrayLength(attributeKeyStringArray);
     const int valueCount = env->GetArrayLength(attributeValueStringArray);
     if (keyCount != valueCount) {
@@ -48,7 +53,7 @@
             JniDataUtils::constructAttributeMap(env, attributeKeyStringArray,
                     attributeValueStringArray);
     return DictFileWritingUtils::createEmptyDictFile(filePathChars, static_cast<int>(dictVersion),
-            CharUtils::convertShortArrayToIntVector(localeCodePoints, localeLength), &attributeMap);
+            localeCodePoints, &attributeMap);
 }
 
 static jfloat latinime_BinaryDictionaryUtils_calcNormalizedScore(JNIEnv *env, jclass clazz,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
index f950cad..ab943a3 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
@@ -69,7 +69,7 @@
 
     // Constructs header information using an attribute map.
     HeaderPolicy(const FormatUtils::FORMAT_VERSION dictFormatVersion,
-            const std::vector<int> locale,
+            const std::vector<int> &locale,
             const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap)
             : mDictFormatVersion(dictFormatVersion),
               mDictionaryFlags(HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
index 5f19534..eefedc3 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
@@ -30,24 +30,45 @@
 namespace latinime {
 
 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory
-                ::newDictionaryStructureWithBufferPolicy(const char *const path,
-                        const int bufOffset, const int size, const bool isUpdatable) {
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForExistingDictFile(
+                const char *const path, const int bufOffset, const int size,
+                const bool isUpdatable) {
     if (FileUtils::existsDir(path)) {
         // Given path represents a directory.
-        return newPolicyforDirectoryDict(path, isUpdatable);
+        return newPolicyForDirectoryDict(path, isUpdatable);
     } else {
         if (isUpdatable) {
             AKLOGE("One file dictionaries don't support updating. path: %s", path);
             ASSERT(false);
             return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
         }
-        return newPolicyforFileDict(path, bufOffset, size);
+        return newPolicyForFileDict(path, bufOffset, size);
     }
 }
 
 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory::newPolicyforDirectoryDict(
+        DictionaryStructureWithBufferPolicyFactory:: newPolicyForOnMemoryDict(
+                const int formatVersion, const std::vector<int> &locale,
+                const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
+    switch (formatVersion) {
+        case FormatUtils::VERSION_4: {
+            HeaderPolicy headerPolicy(FormatUtils::VERSION_4, locale, attributeMap);
+            Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers =
+                    Ver4DictBuffers::createVer4DictBuffers(&headerPolicy,
+                            Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
+            return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
+                    new Ver4PatriciaTriePolicy(std::move(dictBuffers)));
+        }
+        default:
+            AKLOGE("DICT: dictionary format %d is not supported for on memory dictionary",
+                    formatVersion);
+            break;
+    }
+    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
+}
+
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForDirectoryDict(
                 const char *const path, const bool isUpdatable) {
     const int headerFilePathBufSize = PATH_MAX + 1 /* terminator */;
     char headerFilePath[headerFilePathBufSize];
@@ -93,7 +114,7 @@
 }
 
 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory::newPolicyforFileDict(
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForFileDict(
                 const char *const path, const int bufOffset, const int size) {
     // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
     // MmappedBufferPtr if the instance has the responsibility.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
index 6053b7e..f71447e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
@@ -17,7 +17,10 @@
 #ifndef LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
 #define LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
 
+#include <vector>
+
 #include "defines.h"
+#include "suggest/core/policy/dictionary_header_structure_policy.h"
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 
 namespace latinime {
@@ -25,17 +28,22 @@
 class DictionaryStructureWithBufferPolicyFactory {
  public:
     static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newDictionaryStructureWithBufferPolicy(const char *const path, const int bufOffset,
+            newPolicyForExistingDictFile(const char *const path, const int bufOffset,
                     const int size, const bool isUpdatable);
 
+    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+            newPolicyForOnMemoryDict(const int formatVersion,
+                    const std::vector<int> &locale,
+                    const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
+
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);
 
     static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newPolicyforDirectoryDict(const char *const path, const bool isUpdatable);
+            newPolicyForDirectoryDict(const char *const path, const bool isUpdatable);
 
     static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newPolicyforFileDict(const char *const path, const int bufOffset, const int size);
+            newPolicyForFileDict(const char *const path, const int bufOffset, const int size);
 
     static void getHeaderFilePathInDictDir(const char *const dirPath,
             const int outHeaderFileBufSize, char *const outHeaderFilePath);
diff --git a/native/jni/src/utils/char_utils.h b/native/jni/src/utils/char_utils.h
index 98b8966..239419d 100644
--- a/native/jni/src/utils/char_utils.h
+++ b/native/jni/src/utils/char_utils.h
@@ -86,13 +86,6 @@
         return spaceCount;
     }
 
-    static AK_FORCE_INLINE std::vector<int> convertShortArrayToIntVector(
-            const unsigned short *const source, const int length) {
-        std::vector<int> destination;
-        destination.insert(destination.end(), source, source + length);
-        return destination; // Copies the vector
-    }
-
     static unsigned short latin_tolower(const unsigned short c);
     static const std::vector<int> EMPTY_STRING;