aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/event/CombinerChain.java8
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java4
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java15
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java4
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FormatSpec.java3
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DistracterFilter.java23
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java40
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp1
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp117
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h16
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp19
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp4
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h1
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp10
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java43
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java91
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTests.java12
-rw-r--r--tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java6
20 files changed, 297 insertions, 128 deletions
diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 990f7deea..9e7f04d4f 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -56,18 +56,20 @@ public class CombinerChain {
*
* The combiner chain takes events as inputs and outputs code points and combining state.
* For example, if the input language is Japanese, the combining chain will typically perform
- * kana conversion.
+ * kana conversion. This takes a string for initial text, taken to be present before the
+ * cursor: we'll start after this.
*
+ * @param initialText The text that has already been combined so far.
* @param combinerList A list of combiners to be applied in order.
*/
- public CombinerChain(final Combiner... combinerList) {
+ public CombinerChain(final String initialText, final Combiner... combinerList) {
mCombiners = CollectionUtils.newArrayList();
// The dead key combiner is always active, and always first
mCombiners.add(new DeadKeyCombiner());
for (final Combiner combiner : combinerList) {
mCombiners.add(combiner);
}
- mCombinedText = new StringBuilder();
+ mCombinedText = new StringBuilder(initialText);
mStateFeedback = new SpannableStringBuilder();
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 8a2ed1088..3751a3cdb 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -84,6 +84,7 @@ import com.android.inputmethod.latin.utils.CapsModeUtils;
import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.DialogUtils;
import com.android.inputmethod.latin.utils.DistracterFilter;
+import com.android.inputmethod.latin.utils.DistracterFilterUtils;
import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
import com.android.inputmethod.latin.utils.IntentUtils;
import com.android.inputmethod.latin.utils.JniUtils;
@@ -1745,7 +1746,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@UsedForTesting
/* package for test */ DistracterFilter createDistracterFilter() {
- return DistracterFilter.createDistracterFilter(mInputLogic.mSuggest, mKeyboardSwitcher);
+ return DistracterFilterUtils.createDistracterFilter(
+ mInputLogic.mSuggest, mKeyboardSwitcher);
}
public void dumpDictionaryForDebug(final String dictName) {
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index cdee496a8..ac6972928 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -80,7 +80,7 @@ public final class WordComposer {
private boolean mIsFirstCharCapitalized;
public WordComposer() {
- mCombinerChain = new CombinerChain();
+ mCombinerChain = new CombinerChain("");
mEvents = CollectionUtils.newArrayList();
mAutoCorrection = null;
mIsResumed = false;
@@ -92,18 +92,17 @@ public final class WordComposer {
}
/**
- * Restart input with a new combining spec.
+ * Restart the combiners, possibly with a new spec.
* @param combiningSpec The spec string for combining. This is found in the extra value.
*/
- public void restart(final String combiningSpec) {
+ public void restartCombining(final String combiningSpec) {
final String nonNullCombiningSpec = null == combiningSpec ? "" : combiningSpec;
- if (nonNullCombiningSpec.equals(mCombiningSpec)) {
- mCombinerChain.reset();
- } else {
- mCombinerChain = new CombinerChain(CombinerChain.createCombiners(nonNullCombiningSpec));
+ if (!nonNullCombiningSpec.equals(mCombiningSpec)) {
+ mCombinerChain = new CombinerChain(
+ mCombinerChain.getComposingWordWithCombiningFeedback().toString(),
+ CombinerChain.createCombiners(nonNullCombiningSpec));
mCombiningSpec = nonNullCombiningSpec;
}
- reset();
}
/**
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 1156c7737..ea58abc14 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -127,7 +127,7 @@ public final class InputLogic {
public void startInput(final boolean restarting, final EditorInfo editorInfo,
final String combiningSpec) {
mEnteredText = null;
- mWordComposer.restart(combiningSpec);
+ mWordComposer.restartCombining(combiningSpec);
resetComposingState(true /* alsoResetLastComposedWord */);
mDeleteCount = 0;
mSpaceState = SpaceState.NONE;
@@ -150,7 +150,7 @@ public final class InputLogic {
* @param combiningSpec the spec string for the combining rules
*/
public void onSubtypeChanged(final String combiningSpec) {
- mWordComposer.restart(combiningSpec);
+ mWordComposer.restartCombining(combiningSpec);
}
/**
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index 613ff2ba4..f5f072b7a 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -193,8 +193,9 @@ public final class FormatSpec {
// Dictionary version used for testing.
public static final int VERSION4_ONLY_FOR_TESTING = 399;
public static final int VERSION4 = 401;
+ public static final int VERSION4_DEV = 402;
static final int MINIMUM_SUPPORTED_VERSION = VERSION2;
- static final int MAXIMUM_SUPPORTED_VERSION = VERSION4;
+ static final int MAXIMUM_SUPPORTED_VERSION = VERSION4_DEV;
// TODO: Make this value adaptative to content data, store it in the header, and
// use it in the reading code.
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
index 55cbf79b3..0a0379982 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
@@ -17,8 +17,6 @@
package com.android.inputmethod.latin.utils;
import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Suggest;
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
@@ -54,18 +52,6 @@ public class DistracterFilter {
mKeyboard = keyboard;
}
- public static DistracterFilter createDistracterFilter(final Suggest suggest,
- final KeyboardSwitcher keyboardSwitcher) {
- final MainKeyboardView mainKeyboardView = keyboardSwitcher.getMainKeyboardView();
- // TODO: Create Keyboard when mainKeyboardView is null.
- // TODO: Figure out the most reasonable keyboard for the filter. Refer to the
- // spellchecker's logic.
- final Keyboard keyboard = (mainKeyboardView != null) ?
- mainKeyboardView.getKeyboard() : null;
- final DistracterFilter distracterFilter = new DistracterFilter(suggest, keyboard);
- return distracterFilter;
- }
-
private static boolean suggestionExceedsDistracterThreshold(
final SuggestedWordInfo suggestion, final String consideredWord,
final float distracterThreshold) {
@@ -90,19 +76,14 @@ public class DistracterFilter {
*/
public boolean isDistracterToWordsInDictionaries(final String prevWord,
final String testedWord) {
- if (mSuggest == null) {
+ if (mSuggest == null || mKeyboard == null) {
return false;
}
final WordComposer composer = new WordComposer();
final int[] codePoints = StringUtils.toCodePointArray(testedWord);
final int[] coordinates;
- if (null == mKeyboard) {
- coordinates = CoordinateUtils.newCoordinateArray(codePoints.length,
- Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
- } else {
- coordinates = mKeyboard.getCoordinates(codePoints);
- }
+ coordinates = mKeyboard.getCoordinates(codePoints);
composer.setComposingWord(codePoints, coordinates, prevWord);
final int trailingSingleQuotesCount = composer.trailingSingleQuotesCount();
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java
new file mode 100644
index 000000000..df07f976c
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.inputmethod.latin.utils;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
+import com.android.inputmethod.keyboard.MainKeyboardView;
+import com.android.inputmethod.latin.Suggest;
+
+public class DistracterFilterUtils {
+ private DistracterFilterUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static final DistracterFilter createDistracterFilter(final Suggest suggest,
+ final KeyboardSwitcher keyboardSwitcher) {
+ final MainKeyboardView mainKeyboardView = keyboardSwitcher.getMainKeyboardView();
+ // TODO: Create Keyboard when mainKeyboardView is null.
+ // TODO: Figure out the most reasonable keyboard for the filter. Refer to the
+ // spellchecker's logic.
+ final Keyboard keyboard = (mainKeyboardView != null) ?
+ mainKeyboardView.getKeyboard() : null;
+ final DistracterFilter distracterFilter = new DistracterFilter(suggest, keyboard);
+ return distracterFilter;
+ }
+}
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 da24302c2..479d15164 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
@@ -143,6 +143,8 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy {
return FormatUtils::VERSION_4_ONLY_FOR_TESTING;
case FormatUtils::VERSION_4:
return FormatUtils::VERSION_4;
+ case FormatUtils::VERSION_4_DEV:
+ return FormatUtils::VERSION_4_DEV;
default:
return FormatUtils::UNKNOWN_VERSION;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
index 2a9028a9e..a8f8f284b 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
@@ -100,6 +100,7 @@ typedef DictionaryHeaderStructurePolicy::AttributeMap AttributeMap;
return false;
case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
case FormatUtils::VERSION_4:
+ case FormatUtils::VERSION_4_DEV:
return buffer->writeUintAndAdvancePosition(version /* data */,
HEADER_DICTIONARY_VERSION_SIZE, writingPos);
default:
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 c4d18608c..59f1f29e9 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
@@ -19,6 +19,9 @@
#include <climits>
#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
@@ -42,7 +45,7 @@ namespace latinime {
if (isUpdatable) {
AKLOGE("One file dictionaries don't support updating. path: %s", path);
ASSERT(false);
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
+ return nullptr;
}
return newPolicyForFileDict(path, bufOffset, size);
}
@@ -54,26 +57,43 @@ namespace latinime {
const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
FormatUtils::FORMAT_VERSION dictFormatVersion = FormatUtils::getFormatVersion(formatVersion);
switch (dictFormatVersion) {
- case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
case FormatUtils::VERSION_4: {
- HeaderPolicy headerPolicy(dictFormatVersion, locale, attributeMap);
- Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers =
- Ver4DictBuffers::createVer4DictBuffers(&headerPolicy,
- Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
- if (!DynamicPtWritingUtils::writeEmptyDictionary(
- dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
- AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
- }
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
- new Ver4PatriciaTriePolicy(std::move(dictBuffers)));
+ return newPolicyForOnMemoryV4Dict<backward::v401::Ver4DictConstants,
+ backward::v401::Ver4DictBuffers,
+ backward::v401::Ver4DictBuffers::Ver4DictBuffersPtr,
+ backward::v401::Ver4PatriciaTriePolicy>(
+ dictFormatVersion, locale, attributeMap);
+ }
+ case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+ case FormatUtils::VERSION_4_DEV: {
+ return newPolicyForOnMemoryV4Dict<Ver4DictConstants, Ver4DictBuffers,
+ Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
+ dictFormatVersion, locale, attributeMap);
}
default:
AKLOGE("DICT: dictionary format %d is not supported for on memory dictionary",
formatVersion);
break;
}
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
+ return nullptr;
+}
+
+template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+ DictionaryStructureWithBufferPolicyFactory::newPolicyForOnMemoryV4Dict(
+ const FormatUtils::FORMAT_VERSION formatVersion,
+ const std::vector<int> &locale,
+ const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
+ HeaderPolicy headerPolicy(formatVersion, locale, attributeMap);
+ DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers(&headerPolicy,
+ DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
+ if (!DynamicPtWritingUtils::writeEmptyDictionary(
+ dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
+ AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
+ return nullptr;
+ }
+ return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
+ new StructurePolicy(std::move(dictBuffers)));
}
/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
@@ -84,10 +104,10 @@ namespace latinime {
getHeaderFilePathInDictDir(path, headerFilePathBufSize, headerFilePath);
// Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
// MmappedBufferPtr if the instance has the responsibility.
- MmappedBuffer::MmappedBufferPtr mmappedBuffer(
- MmappedBuffer::openBuffer(headerFilePath, isUpdatable));
+ MmappedBuffer::MmappedBufferPtr mmappedBuffer =
+ MmappedBuffer::openBuffer(headerFilePath, isUpdatable);
if (!mmappedBuffer) {
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
+ return nullptr;
}
const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::detectFormatVersion(
mmappedBuffer->getBuffer(), mmappedBuffer->getBufferSize());
@@ -95,34 +115,50 @@ namespace latinime {
case FormatUtils::VERSION_2:
AKLOGE("Given path is a directory but the format is version 2. path: %s", path);
break;
- case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
case FormatUtils::VERSION_4: {
- const int dictDirPathBufSize = strlen(headerFilePath) + 1 /* terminator */;
- char dictPath[dictDirPathBufSize];
- if (!FileUtils::getFilePathWithoutSuffix(headerFilePath,
- Ver4DictConstants::HEADER_FILE_EXTENSION, dictDirPathBufSize, dictPath)) {
- AKLOGE("Dictionary file name is not valid as a ver4 dictionary. path: %s", path);
- ASSERT(false);
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
- }
- Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
- Ver4DictBuffers::openVer4DictBuffers(dictPath, std::move(mmappedBuffer),
- formatVersion));
- if (!dictBuffers || !dictBuffers->isValid()) {
- AKLOGE("DICT: The dictionary doesn't satisfy ver4 format requirements. path: %s",
- path);
- ASSERT(false);
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
- }
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
- new Ver4PatriciaTriePolicy(std::move(dictBuffers)));
+ return newPolicyForV4Dict<backward::v401::Ver4DictConstants,
+ backward::v401::Ver4DictBuffers,
+ backward::v401::Ver4DictBuffers::Ver4DictBuffersPtr,
+ backward::v401::Ver4PatriciaTriePolicy>(
+ headerFilePath, formatVersion, std::move(mmappedBuffer));
+ }
+ case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+ case FormatUtils::VERSION_4_DEV: {
+ return newPolicyForV4Dict<Ver4DictConstants, Ver4DictBuffers,
+ Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
+ headerFilePath, formatVersion, std::move(mmappedBuffer));
}
default:
AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
break;
}
ASSERT(false);
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
+ return nullptr;
+}
+
+template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+ DictionaryStructureWithBufferPolicyFactory::newPolicyForV4Dict(
+ const char *const headerFilePath, const FormatUtils::FORMAT_VERSION formatVersion,
+ MmappedBuffer::MmappedBufferPtr &&mmappedBuffer) {
+ const int dictDirPathBufSize = strlen(headerFilePath) + 1 /* terminator */;
+ char dictPath[dictDirPathBufSize];
+ if (!FileUtils::getFilePathWithoutSuffix(headerFilePath,
+ DictConstants::HEADER_FILE_EXTENSION, dictDirPathBufSize, dictPath)) {
+ AKLOGE("Dictionary file name is not valid as a ver4 dictionary. path: %s", path);
+ ASSERT(false);
+ return nullptr;
+ }
+ DictBuffersPtr dictBuffers =
+ DictBuffers::openVer4DictBuffers(dictPath, std::move(mmappedBuffer), formatVersion);
+ if (!dictBuffers || !dictBuffers->isValid()) {
+ AKLOGE("DICT: The dictionary doesn't satisfy ver4 format requirements. path: %s",
+ path);
+ ASSERT(false);
+ return nullptr;
+ }
+ return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
+ new StructurePolicy(std::move(dictBuffers)));
}
/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
@@ -133,7 +169,7 @@ namespace latinime {
MmappedBuffer::MmappedBufferPtr mmappedBuffer(
MmappedBuffer::openBuffer(path, bufOffset, size, false /* isUpdatable */));
if (!mmappedBuffer) {
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
+ return nullptr;
}
switch (FormatUtils::detectFormatVersion(mmappedBuffer->getBuffer(),
mmappedBuffer->getBufferSize())) {
@@ -142,6 +178,7 @@ namespace latinime {
new PatriciaTriePolicy(std::move(mmappedBuffer)));
case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
case FormatUtils::VERSION_4:
+ case FormatUtils::VERSION_4_DEV:
AKLOGE("Given path is a file but the format is version 4. path: %s", path);
break;
default:
@@ -149,7 +186,7 @@ namespace latinime {
break;
}
ASSERT(false);
- return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
+ return nullptr;
}
/* static */ void DictionaryStructureWithBufferPolicyFactory::getHeaderFilePathInDictDir(
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 f71447e23..768454d8d 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
@@ -22,6 +22,8 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_header_structure_policy.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "suggest/policyimpl/dictionary/utils/format_utils.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
namespace latinime {
@@ -32,16 +34,26 @@ class DictionaryStructureWithBufferPolicyFactory {
const int size, const bool isUpdatable);
static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
- newPolicyForOnMemoryDict(const int formatVersion,
- const std::vector<int> &locale,
+ newPolicyForOnMemoryDict(const int formatVersion, const std::vector<int> &locale,
const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);
+ template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+ static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+ newPolicyForOnMemoryV4Dict(const FormatUtils::FORMAT_VERSION formatVersion,
+ const std::vector<int> &locale,
+ const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
+
static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
newPolicyForDirectoryDict(const char *const path, const bool isUpdatable);
+ template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+ static DictionaryStructureWithBufferPolicy::StructurePolicyPtr newPolicyForV4Dict(
+ const char *const headerFilePath, const FormatUtils::FORMAT_VERSION formatVersion,
+ MmappedBuffer::MmappedBufferPtr &&mmappedBuffer);
+
static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
newPolicyForFileDict(const char *const path, const int bufOffset, const int size);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
index 80970c7f8..105363db5 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
@@ -40,10 +41,16 @@ const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE =
TimeKeeper::setCurrentTime();
const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::getFormatVersion(dictVersion);
switch (formatVersion) {
- case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
case FormatUtils::VERSION_4:
- return createEmptyV4DictFile(filePath, localeAsCodePointVector, attributeMap,
- formatVersion);
+ return createEmptyV4DictFile<backward::v401::Ver4DictConstants,
+ backward::v401::Ver4DictBuffers,
+ backward::v401::Ver4DictBuffers::Ver4DictBuffersPtr>(
+ filePath, localeAsCodePointVector, attributeMap, formatVersion);
+ case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+ case FormatUtils::VERSION_4_DEV:
+ return createEmptyV4DictFile<Ver4DictConstants, Ver4DictBuffers,
+ Ver4DictBuffers::Ver4DictBuffersPtr>(
+ filePath, localeAsCodePointVector, attributeMap, formatVersion);
default:
AKLOGE("Cannot create dictionary %s because format version %d is not supported.",
filePath, dictVersion);
@@ -51,14 +58,14 @@ const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE =
}
}
+template<class DictConstants, class DictBuffers, class DictBuffersPtr>
/* static */ bool DictFileWritingUtils::createEmptyV4DictFile(const char *const dirPath,
const std::vector<int> localeAsCodePointVector,
const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
const FormatUtils::FORMAT_VERSION formatVersion) {
HeaderPolicy headerPolicy(formatVersion, localeAsCodePointVector, attributeMap);
- Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
- Ver4DictBuffers::createVer4DictBuffers(&headerPolicy,
- Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE));
+ DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers(&headerPolicy,
+ DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
headerPolicy.fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
0 /* unigramCount */, 0 /* bigramCount */,
0 /* extendedRegionSize */, dictBuffers->getWritableHeaderBuffer());
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
index a822989db..5df5856d2 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
@@ -45,6 +45,12 @@ class DictFileWritingUtils {
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DictFileWritingUtils);
+ static bool createEmptyV401DictFile(const char *const filePath,
+ const std::vector<int> localeAsCodePointVector,
+ const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
+ const FormatUtils::FORMAT_VERSION formatVersion);
+
+ template<class DictConstants, class DictBuffers, class DictBuffersPtr>
static bool createEmptyV4DictFile(const char *const filePath,
const std::vector<int> localeAsCodePointVector,
const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
index a8518cdca..ba405b07e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
@@ -33,6 +33,8 @@ const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
return VERSION_4_ONLY_FOR_TESTING;
case VERSION_4:
return VERSION_4;
+ case VERSION_4_DEV:
+ return VERSION_4_DEV;
default:
return UNKNOWN_VERSION;
}
@@ -62,6 +64,8 @@ const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
return VERSION_4_ONLY_FOR_TESTING;
} else if (ByteArrayUtils::readUint16(dict, 4) == VERSION_4) {
return VERSION_4;
+ } else if (ByteArrayUtils::readUint16(dict, 4) == VERSION_4_DEV) {
+ return VERSION_4_DEV;
} else {
return UNKNOWN_VERSION;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
index 20dfb9d8c..c47f30ca4 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
@@ -33,6 +33,7 @@ class FormatUtils {
VERSION_2 = 2,
VERSION_4_ONLY_FOR_TESTING = 399,
VERSION_4 = 401,
+ VERSION_4_DEV = 402,
UNKNOWN_VERSION = -1
};
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp
index d3e0c237f..4a126ff85 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp
@@ -33,7 +33,7 @@ namespace latinime {
const int mmapFd = open(path, O_RDONLY);
if (mmapFd < 0) {
AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
- return MmappedBufferPtr(nullptr);
+ return nullptr;
}
const int pagesize = sysconf(_SC_PAGESIZE);
const int offset = bufferOffset % pagesize;
@@ -45,13 +45,13 @@ namespace latinime {
if (mmappedBuffer == MAP_FAILED) {
AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
close(mmapFd);
- return MmappedBufferPtr(nullptr);
+ return nullptr;
}
uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
if (!buffer) {
AKLOGE("DICT: buffer is null");
close(mmapFd);
- return MmappedBufferPtr(nullptr);
+ return nullptr;
}
return MmappedBufferPtr(new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize,
mmapFd, isUpdatable));
@@ -61,7 +61,7 @@ namespace latinime {
const char *const path, const bool isUpdatable) {
const int fileSize = FileUtils::getFileSize(path);
if (fileSize == -1) {
- return MmappedBufferPtr(nullptr);
+ return nullptr;
} else if (fileSize == 0) {
return MmappedBufferPtr(new MmappedBuffer(isUpdatable));
} else {
@@ -76,7 +76,7 @@ namespace latinime {
const int filePathLength = snprintf(filePath, filePathBufferSize, "%s%s", dirPath,
fileName);
if (filePathLength >= filePathBufferSize) {
- return MmappedBufferPtr(nullptr);
+ return nullptr;
}
return openBuffer(filePath, isUpdatable);
}
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index 35d9a4e18..90b90ffb5 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -46,6 +46,8 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
private static final String TEST_LOCALE = "test";
private static final int DUMMY_PROBABILITY = 0;
+ private static final int[] DICT_FORMAT_VERSIONS =
+ new int[] { FormatSpec.VERSION4, FormatSpec.VERSION4_DEV };
private int mCurrentTime = 0;
@@ -94,7 +96,8 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
private File createEmptyDictionaryAndGetFile(final String dictId,
final int formatVersion) throws IOException {
if (formatVersion == FormatSpec.VERSION4
- || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING) {
+ || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING
+ || formatVersion == FormatSpec.VERSION4_DEV) {
return createEmptyVer4DictionaryAndGetFile(dictId, formatVersion);
} else {
throw new IOException("Dictionary format version " + formatVersion
@@ -120,7 +123,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
return file;
} else {
throw new IOException("Empty dictionary " + file.getAbsolutePath()
- + " cannot be created.");
+ + " cannot be created. Foramt version: " + formatVersion);
}
}
@@ -133,7 +136,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testReadDictInJavaSide() {
- testReadDictInJavaSide(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testReadDictInJavaSide(formatVersion);
+ }
}
private void testReadDictInJavaSide(final int formatVersion) {
@@ -178,10 +183,6 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testControlCurrentTime() {
- testControlCurrentTime(FormatSpec.VERSION4);
- }
-
- private void testControlCurrentTime(final int formatVersion) {
final int TEST_COUNT = 1000;
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
@@ -197,7 +198,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testAddValidAndInvalidWords() {
- testAddValidAndInvalidWords(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddValidAndInvalidWords(formatVersion);
+ }
}
private void testAddValidAndInvalidWords(final int formatVersion) {
@@ -240,7 +243,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testDecayingProbability() {
- testDecayingProbability(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testDecayingProbability(formatVersion);
+ }
}
private void testDecayingProbability(final int formatVersion) {
@@ -295,7 +300,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testAddManyUnigramsToDecayingDict() {
- testAddManyUnigramsToDecayingDict(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddManyUnigramsToDecayingDict(formatVersion);
+ }
}
private void testAddManyUnigramsToDecayingDict(final int formatVersion) {
@@ -354,7 +361,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testOverflowUnigrams() {
- testOverflowUnigrams(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testOverflowUnigrams(formatVersion);
+ }
}
private void testOverflowUnigrams(final int formatVersion) {
@@ -413,7 +422,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testAddManyBigramsToDecayingDict() {
- testAddManyBigramsToDecayingDict(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddManyBigramsToDecayingDict(formatVersion);
+ }
}
private void testAddManyBigramsToDecayingDict(final int formatVersion) {
@@ -487,7 +498,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testOverflowBigrams() {
- testOverflowBigrams(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testOverflowBigrams(formatVersion);
+ }
}
private void testOverflowBigrams(final int formatVersion) {
@@ -566,7 +579,9 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
public void testDictMigration() {
- testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
+ }
}
private void testDictMigration(final int fromFormatVersion, final int toFormatVersion) {
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 770e76e5f..cfeed0aa4 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -43,11 +43,14 @@ import java.util.Random;
public class BinaryDictionaryTests extends AndroidTestCase {
private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
private static final String TEST_LOCALE = "test";
+ private static final int[] DICT_FORMAT_VERSIONS =
+ new int[] { FormatSpec.VERSION4, FormatSpec.VERSION4_DEV };
private File createEmptyDictionaryAndGetFile(final String dictId,
final int formatVersion) throws IOException {
if (formatVersion == FormatSpec.VERSION4
- || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING) {
+ || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING
+ || formatVersion == FormatSpec.VERSION4_DEV) {
return createEmptyVer4DictionaryAndGetFile(dictId, formatVersion);
} else {
throw new IOException("Dictionary format version " + formatVersion
@@ -67,12 +70,14 @@ public class BinaryDictionaryTests extends AndroidTestCase {
return file;
} else {
throw new IOException("Empty dictionary " + file.getAbsolutePath()
- + " cannot be created.");
+ + " cannot be created. Format version: " + formatVersion);
}
}
public void testIsValidDictionary() {
- testIsValidDictionary(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testIsValidDictionary(formatVersion);
+ }
}
private void testIsValidDictionary(final int formatVersion) {
@@ -100,7 +105,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testConstructingDictionaryOnMemory() {
- testConstructingDictionaryOnMemory(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testConstructingDictionaryOnMemory(formatVersion);
+ }
}
private void testConstructingDictionaryOnMemory(final int formatVersion) {
@@ -131,7 +138,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddTooLongWord() {
- testAddTooLongWord(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddTooLongWord(formatVersion);
+ }
}
private void testAddTooLongWord(final int formatVersion) {
@@ -190,7 +199,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddUnigramWord() {
- testAddUnigramWord(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddUnigramWord(formatVersion);
+ }
}
private void testAddUnigramWord(final int formatVersion) {
@@ -232,7 +243,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testRandomlyAddUnigramWord() {
- testRandomlyAddUnigramWord(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testRandomlyAddUnigramWord(formatVersion);
+ }
}
private void testRandomlyAddUnigramWord(final int formatVersion) {
@@ -268,7 +281,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddBigramWords() {
- testAddBigramWords(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddBigramWords(formatVersion);
+ }
}
private void testAddBigramWords(final int formatVersion) {
@@ -336,7 +351,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testRandomlyAddBigramWords() {
- testRandomlyAddBigramWords(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testRandomlyAddBigramWords(formatVersion);
+ }
}
private void testRandomlyAddBigramWords(final int formatVersion) {
@@ -397,7 +414,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testRemoveBigramWords() {
- testRemoveBigramWords(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testRemoveBigramWords(formatVersion);
+ }
}
private void testRemoveBigramWords(final int formatVersion) {
@@ -447,7 +466,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testFlushDictionary() {
- testFlushDictionary(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testFlushDictionary(formatVersion);
+ }
}
private void testFlushDictionary(final int formatVersion) {
@@ -499,7 +520,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testFlushWithGCDictionary() {
- testFlushWithGCDictionary(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testFlushWithGCDictionary(formatVersion);
+ }
}
private void testFlushWithGCDictionary(final int formatVersion) {
@@ -547,7 +570,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddBigramWordsAndFlashWithGC() {
- testAddBigramWordsAndFlashWithGC(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddBigramWordsAndFlashWithGC(formatVersion);
+ }
}
// TODO: Evaluate performance of GC
@@ -616,7 +641,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testRandomOperationsAndFlashWithGC() {
- testRandomOperationsAndFlashWithGC(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testRandomOperationsAndFlashWithGC(formatVersion);
+ }
}
private void testRandomOperationsAndFlashWithGC(final int formatVersion) {
@@ -727,7 +754,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddManyUnigramsAndFlushWithGC() {
- testAddManyUnigramsAndFlushWithGC(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddManyUnigramsAndFlushWithGC(formatVersion);
+ }
}
private void testAddManyUnigramsAndFlushWithGC(final int formatVersion) {
@@ -775,7 +804,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testUnigramAndBigramCount() {
- testUnigramAndBigramCount(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testUnigramAndBigramCount(formatVersion);
+ }
}
private void testUnigramAndBigramCount(final int formatVersion) {
@@ -834,7 +865,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddMultipleDictionaryEntries() {
- testAddMultipleDictionaryEntries(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddMultipleDictionaryEntries(formatVersion);
+ }
}
private void testAddMultipleDictionaryEntries(final int formatVersion) {
@@ -896,7 +929,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testGetWordProperties() {
- testGetWordProperties(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testGetWordProperties(formatVersion);
+ }
}
private void testGetWordProperties(final int formatVersion) {
@@ -995,7 +1030,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testIterateAllWords() {
- testIterateAllWords(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testIterateAllWords(formatVersion);
+ }
}
private void testIterateAllWords(final int formatVersion) {
@@ -1091,7 +1128,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddShortcuts() {
- testAddShortcuts(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddShortcuts(formatVersion);
+ }
}
private void testAddShortcuts(final int formatVersion) {
@@ -1151,7 +1190,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testAddManyShortcuts() {
- testAddManyShortcuts(FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testAddManyShortcuts(formatVersion);
+ }
}
private void testAddManyShortcuts(final int formatVersion) {
@@ -1227,7 +1268,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testDictMigration() {
- testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
+ }
}
private void testDictMigration(final int fromFormatVersion, final int toFormatVersion) {
@@ -1271,7 +1314,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
public void testLargeDictMigration() {
- testLargeDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, FormatSpec.VERSION4);
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testLargeDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
+ }
}
private void testLargeDictMigration(final int fromFormatVersion, final int toFormatVersion) {
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 29423e8e3..a9444160f 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -600,4 +600,16 @@ public class InputLogicTests extends InputTestsBase {
assertEquals("type words letter by letter", EXPECTED_RESULT,
mEditText.getText().toString());
}
+
+ public void testSwitchLanguages() {
+ final String WORD_TO_TYPE_FIRST_PART = "com";
+ final String WORD_TO_TYPE_SECOND_PART = "md ";
+ final String EXPECTED_RESULT = "comme ";
+ changeLanguage("en");
+ type(WORD_TO_TYPE_FIRST_PART);
+ changeLanguage("fr");
+ type(WORD_TO_TYPE_SECOND_PART);
+ assertEquals("Composing continues after switching languages", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
}
diff --git a/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java b/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
index 47f781e62..538d759c8 100644
--- a/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
+++ b/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
@@ -28,8 +28,10 @@ import java.util.ArrayList;
// TODO: there should not be a dependency to this in dicttool, so there
// should be a sensible way to separate them cleanly.
public class CombinerChain {
- private StringBuilder mComposingWord = new StringBuilder();
- public CombinerChain(final Combiner... combinerList) {}
+ private StringBuilder mComposingWord;
+ public CombinerChain(final String initialText, final Combiner... combinerList) {
+ mComposingWord = new StringBuilder(initialText);
+ }
public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
mComposingWord.append(newEvent.getTextToCommit());