aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java47
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.h11
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_utils.cpp11
-rw-r--r--native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp64
-rw-r--r--native/jni/src/suggest/core/dictionary/multi_bigram_map.h25
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp4
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h2
7 files changed, 85 insertions, 79 deletions
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index f2a6f3b2e..e2feb7c4d 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -405,10 +405,11 @@ public final class InputLogic {
final int keyboardShiftMode,
// TODO: remove these arguments
final int currentKeyboardScriptId, final LatinIME.UIHandler handler) {
- final InputTransaction inputTransaction = new InputTransaction(settingsValues, event,
- SystemClock.uptimeMillis(), mSpaceState,
+ final Event processedEvent = mWordComposer.processEvent(event);
+ final InputTransaction inputTransaction = new InputTransaction(settingsValues,
+ processedEvent, SystemClock.uptimeMillis(), mSpaceState,
getActualCapsMode(settingsValues, keyboardShiftMode));
- if (event.mKeyCode != Constants.CODE_DELETE
+ if (processedEvent.mKeyCode != Constants.CODE_DELETE
|| inputTransaction.mTimestamp > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) {
mDeleteCount = 0;
}
@@ -419,14 +420,14 @@ public final class InputLogic {
}
// TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state.
- if (event.mCodePoint != Constants.CODE_SPACE) {
+ if (processedEvent.mCodePoint != Constants.CODE_SPACE) {
cancelDoubleSpacePeriodCountdown();
}
boolean didAutoCorrect = false;
- if (event.isFunctionalKeyEvent()) {
+ if (processedEvent.isFunctionalKeyEvent()) {
// A special key, like delete, shift, emoji, or the settings key.
- switch (event.mKeyCode) {
+ switch (processedEvent.mKeyCode) {
case Constants.CODE_DELETE:
handleBackspace(inputTransaction, currentKeyboardScriptId);
// Backspace is a functional key, but it affects the contents of the editor.
@@ -478,7 +479,8 @@ public final class InputLogic {
case Constants.CODE_SHIFT_ENTER:
// TODO: remove this object
final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
- event.mKeyCode, event.mX, event.mY, event.isKeyRepeat());
+ processedEvent.mKeyCode, processedEvent.mX, processedEvent.mY,
+ processedEvent.isKeyRepeat());
final InputTransaction tmpTransaction = new InputTransaction(
inputTransaction.mSettingsValues, tmpEvent,
inputTransaction.mTimestamp, inputTransaction.mSpaceState,
@@ -489,11 +491,11 @@ public final class InputLogic {
inputTransaction.setDidAffectContents();
break;
default:
- throw new RuntimeException("Unknown key code : " + event.mKeyCode);
+ throw new RuntimeException("Unknown key code : " + processedEvent.mKeyCode);
}
} else {
inputTransaction.setDidAffectContents();
- switch (event.mCodePoint) {
+ switch (processedEvent.mCodePoint) {
case Constants.CODE_ENTER:
final EditorInfo editorInfo = getCurrentInputEditorInfo();
final int imeOptionsActionId =
@@ -522,11 +524,11 @@ public final class InputLogic {
break;
}
}
- if (!didAutoCorrect && event.mKeyCode != Constants.CODE_SHIFT
- && event.mKeyCode != Constants.CODE_CAPSLOCK
- && event.mKeyCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
+ if (!didAutoCorrect && processedEvent.mKeyCode != Constants.CODE_SHIFT
+ && processedEvent.mKeyCode != Constants.CODE_CAPSLOCK
+ && processedEvent.mKeyCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
mLastComposedWord.deactivate();
- if (Constants.CODE_DELETE != event.mKeyCode) {
+ if (Constants.CODE_DELETE != processedEvent.mKeyCode) {
mEnteredText = null;
}
mConnection.endBatchEdit();
@@ -712,8 +714,7 @@ public final class InputLogic {
*/
private void handleNonSeparator(final SettingsValues settingsValues,
final InputTransaction inputTransaction) {
- final Event processedEvent = mWordComposer.processEvent(inputTransaction.mEvent);
- final int codePoint = processedEvent.mCodePoint;
+ final int codePoint = inputTransaction.mEvent.mCodePoint;
// TODO: refactor this method to stop flipping isComposingWord around all the time, and
// make it shorter (possibly cut into several pieces). Also factor handleNonSpecialCharacter
// which has the same name as other handle* methods but is not the same.
@@ -763,7 +764,7 @@ public final class InputLogic {
resetComposingState(false /* alsoResetLastComposedWord */);
}
if (isComposingWord) {
- mWordComposer.applyProcessedEvent(processedEvent);
+ mWordComposer.applyProcessedEvent(inputTransaction.mEvent);
// If it's the first letter, make note of auto-caps state
if (mWordComposer.isSingleLetter()) {
mWordComposer.setCapitalizedModeAtStartComposingTime(inputTransaction.mShiftState);
@@ -772,7 +773,7 @@ public final class InputLogic {
mWordComposer.getTypedWord()), 1);
} else {
final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
- inputTransaction, processedEvent.isSuggestionStripPress());
+ inputTransaction);
if (swapWeakSpace && trySwapSwapperAndSpace(inputTransaction)) {
mSpaceState = SpaceState.WEAK;
@@ -823,7 +824,7 @@ public final class InputLogic {
}
final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
- inputTransaction, isFromSuggestionStrip);
+ inputTransaction);
final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint
&& mConnection.isInsideDoubleQuoteOrAfterDigit();
@@ -903,7 +904,7 @@ public final class InputLogic {
private void handleBackspace(final InputTransaction inputTransaction,
// TODO: remove this argument, put it into settingsValues
final int currentKeyboardScriptId) {
- final Event processedEvent = mWordComposer.processEvent(inputTransaction.mEvent);
+ final Event event = inputTransaction.mEvent;
mSpaceState = SpaceState.NONE;
mDeleteCount++;
@@ -915,7 +916,7 @@ public final class InputLogic {
// Then again, even in the case of a key repeat, if the cursor is at start of text, it
// can't go any further back, so we can update right away even if it's a key repeat.
final int shiftUpdateKind =
- processedEvent.isKeyRepeat() && mConnection.getExpectedSelectionStart() > 0
+ event.isKeyRepeat() && mConnection.getExpectedSelectionStart() > 0
? InputTransaction.SHIFT_UPDATE_LATER : InputTransaction.SHIFT_UPDATE_NOW;
inputTransaction.requireShiftUpdate(shiftUpdateKind);
@@ -935,7 +936,7 @@ public final class InputLogic {
mDictionaryFacilitator.removeWordFromPersonalizedDicts(rejectedSuggestion);
}
} else {
- mWordComposer.applyProcessedEvent(processedEvent);
+ mWordComposer.applyProcessedEvent(event);
}
if (mWordComposer.isComposingWord()) {
mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
@@ -1072,12 +1073,12 @@ public final class InputLogic {
/*
* Strip a trailing space if necessary and returns whether it's a swap weak space situation.
* @param inputTransaction The transaction in progress.
- * @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip.
* @return whether we should swap the space instead of removing it.
*/
private boolean tryStripSpaceAndReturnWhetherShouldSwapInstead(
- final InputTransaction inputTransaction, final boolean isFromSuggestionStrip) {
+ final InputTransaction inputTransaction) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
+ final boolean isFromSuggestionStrip = inputTransaction.mEvent.isSuggestionStripPress();
if (Constants.CODE_ENTER == codePoint &&
SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) {
mConnection.removeTrailingSpace();
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 92f39ea25..d1b2c87be 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -117,7 +117,7 @@ class DicNode {
int newPrevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
newPrevWordsPtNodePos[0] = dicNode->mDicNodeProperties.getPtNodePos();
for (size_t i = 1; i < NELEMS(newPrevWordsPtNodePos); ++i) {
- newPrevWordsPtNodePos[i] = dicNode->getNthPrevWordTerminalPtNodePos(i);
+ newPrevWordsPtNodePos[i] = dicNode->getPrevWordsTerminalPtNodePos()[i - 1];
}
mDicNodeProperties.init(rootPtNodeArrayPos, newPrevWordsPtNodePos);
mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
@@ -208,12 +208,9 @@ class DicNode {
return mDicNodeProperties.getPtNodePos();
}
- // Used to get n-gram probability in DicNodeUtils. n is 1-indexed.
- int getNthPrevWordTerminalPtNodePos(const int n) const {
- if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
- return NOT_A_DICT_POS;
- }
- return mDicNodeProperties.getPrevWordsTerminalPtNodePos()[n - 1];
+ // TODO: Use view class to return PtNodePos array.
+ const int *getPrevWordsTerminalPtNodePos() const {
+ return mDicNodeProperties.getPrevWordsTerminalPtNodePos();
}
// Used in DicNodeUtils
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index 4445f4aaf..69ea67418 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -85,17 +85,10 @@ namespace latinime {
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
const DicNode *const dicNode, MultiBigramMap *const multiBigramMap) {
const int unigramProbability = dicNode->getProbability();
- const int ptNodePos = dicNode->getPtNodePos();
- const int prevWordTerminalPtNodePos = dicNode->getNthPrevWordTerminalPtNodePos(1 /* n */);
- if (NOT_A_DICT_POS == ptNodePos || NOT_A_DICT_POS == prevWordTerminalPtNodePos) {
- // Note: Normally wordPos comes from the dictionary and should never equal
- // NOT_A_VALID_WORD_POS.
- return dictionaryStructurePolicy->getProbability(unigramProbability,
- NOT_A_PROBABILITY);
- }
if (multiBigramMap) {
+ const int *const prevWordsPtNodePos = dicNode->getPrevWordsTerminalPtNodePos();
return multiBigramMap->getBigramProbability(dictionaryStructurePolicy,
- prevWordTerminalPtNodePos, ptNodePos, unigramProbability);
+ prevWordsPtNodePos, dicNode->getPtNodePos(), unigramProbability);
}
return dictionaryStructurePolicy->getProbability(unigramProbability,
NOT_A_PROBABILITY);
diff --git a/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp b/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
index 012e4dc9c..91f33a8dd 100644
--- a/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
+++ b/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
@@ -35,34 +35,30 @@ const int MultiBigramMap::BigramMap::DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP =
// Also caches the bigrams if there is space remaining and they have not been cached already.
int MultiBigramMap::getBigramProbability(
const DictionaryStructureWithBufferPolicy *const structurePolicy,
- const int wordPosition, const int nextWordPosition, const int unigramProbability) {
+ const int *const prevWordsPtNodePos, const int nextWordPosition,
+ const int unigramProbability) {
+ if (!prevWordsPtNodePos || prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
+ return structurePolicy->getProbability(unigramProbability, NOT_A_PROBABILITY);
+ }
std::unordered_map<int, BigramMap>::const_iterator mapPosition =
- mBigramMaps.find(wordPosition);
+ mBigramMaps.find(prevWordsPtNodePos[0]);
if (mapPosition != mBigramMaps.end()) {
return mapPosition->second.getBigramProbability(structurePolicy, nextWordPosition,
unigramProbability);
}
if (mBigramMaps.size() < MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP) {
- addBigramsForWordPosition(structurePolicy, wordPosition);
- return mBigramMaps[wordPosition].getBigramProbability(structurePolicy,
+ addBigramsForWordPosition(structurePolicy, prevWordsPtNodePos);
+ return mBigramMaps[prevWordsPtNodePos[0]].getBigramProbability(structurePolicy,
nextWordPosition, unigramProbability);
}
- return readBigramProbabilityFromBinaryDictionary(structurePolicy, wordPosition,
+ return readBigramProbabilityFromBinaryDictionary(structurePolicy, prevWordsPtNodePos,
nextWordPosition, unigramProbability);
}
void MultiBigramMap::BigramMap::init(
- const DictionaryStructureWithBufferPolicy *const structurePolicy, const int nodePos) {
- BinaryDictionaryBigramsIterator bigramsIt =
- structurePolicy->getBigramsIteratorOfPtNode(nodePos);
- while (bigramsIt.hasNext()) {
- bigramsIt.next();
- if (bigramsIt.getBigramPos() == NOT_A_DICT_POS) {
- continue;
- }
- mBigramMap[bigramsIt.getBigramPos()] = bigramsIt.getProbability();
- mBloomFilter.setInFilter(bigramsIt.getBigramPos());
- }
+ const DictionaryStructureWithBufferPolicy *const structurePolicy,
+ const int *const prevWordsPtNodePos) {
+ structurePolicy->iterateNgramEntries(prevWordsPtNodePos, this /* listener */);
}
int MultiBigramMap::BigramMap::getBigramProbability(
@@ -79,25 +75,33 @@ int MultiBigramMap::BigramMap::getBigramProbability(
return structurePolicy->getProbability(unigramProbability, bigramProbability);
}
+void MultiBigramMap::BigramMap::onVisitEntry(const int ngramProbability,
+ const int targetPtNodePos) {
+ if (targetPtNodePos == NOT_A_DICT_POS) {
+ return;
+ }
+ mBigramMap[targetPtNodePos] = ngramProbability;
+ mBloomFilter.setInFilter(targetPtNodePos);
+}
+
void MultiBigramMap::addBigramsForWordPosition(
- const DictionaryStructureWithBufferPolicy *const structurePolicy, const int position) {
- mBigramMaps[position].init(structurePolicy, position);
+ const DictionaryStructureWithBufferPolicy *const structurePolicy,
+ const int *const prevWordsPtNodePos) {
+ if (prevWordsPtNodePos) {
+ mBigramMaps[prevWordsPtNodePos[0]].init(structurePolicy, prevWordsPtNodePos);
+ }
}
int MultiBigramMap::readBigramProbabilityFromBinaryDictionary(
- const DictionaryStructureWithBufferPolicy *const structurePolicy, const int nodePos,
- const int nextWordPosition, const int unigramProbability) {
- int bigramProbability = NOT_A_PROBABILITY;
- BinaryDictionaryBigramsIterator bigramsIt =
- structurePolicy->getBigramsIteratorOfPtNode(nodePos);
- while (bigramsIt.hasNext()) {
- bigramsIt.next();
- if (bigramsIt.getBigramPos() == nextWordPosition) {
- bigramProbability = bigramsIt.getProbability();
- break;
- }
+ const DictionaryStructureWithBufferPolicy *const structurePolicy,
+ const int *const prevWordsPtNodePos, const int nextWordPosition,
+ const int unigramProbability) {
+ const int bigramProbability = structurePolicy->getProbabilityOfPtNode(prevWordsPtNodePos,
+ nextWordPosition);
+ if (bigramProbability != NOT_A_PROBABILITY) {
+ return bigramProbability;
}
- return structurePolicy->getProbability(unigramProbability, bigramProbability);
+ return structurePolicy->getProbability(unigramProbability, NOT_A_PROBABILITY);
}
} // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/multi_bigram_map.h b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
index 195b5e22f..ad36dde83 100644
--- a/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
+++ b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
@@ -23,6 +23,7 @@
#include "defines.h"
#include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h"
#include "suggest/core/dictionary/bloom_filter.h"
+#include "suggest/core/dictionary/ngram_listener.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
namespace latinime {
@@ -38,7 +39,8 @@ class MultiBigramMap {
// Look up the bigram probability for the given word pair from the cached bigram maps.
// Also caches the bigrams if there is space remaining and they have not been cached already.
int getBigramProbability(const DictionaryStructureWithBufferPolicy *const structurePolicy,
- const int wordPosition, const int nextWordPosition, const int unigramProbability);
+ const int *const prevWordsPtNodePos, const int nextWordPosition,
+ const int unigramProbability);
void clear() {
mBigramMaps.clear();
@@ -47,32 +49,35 @@ class MultiBigramMap {
private:
DISALLOW_COPY_AND_ASSIGN(MultiBigramMap);
- class BigramMap {
+ class BigramMap : public NgramListener {
public:
BigramMap() : mBigramMap(DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP), mBloomFilter() {}
- ~BigramMap() {}
+ // Copy constructor needed for std::unordered_map.
+ BigramMap(const BigramMap &bigramMap)
+ : mBigramMap(bigramMap.mBigramMap), mBloomFilter(bigramMap.mBloomFilter) {}
+ virtual ~BigramMap() {}
void init(const DictionaryStructureWithBufferPolicy *const structurePolicy,
- const int nodePos);
-
+ const int *const prevWordsPtNodePos);
int getBigramProbability(
const DictionaryStructureWithBufferPolicy *const structurePolicy,
const int nextWordPosition, const int unigramProbability) const;
+ virtual void onVisitEntry(const int ngramProbability, const int targetPtNodePos);
private:
- // NOTE: The BigramMap class doesn't use DISALLOW_COPY_AND_ASSIGN() because its default
- // copy constructor is needed for use in hash_map.
static const int DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP;
std::unordered_map<int, int> mBigramMap;
BloomFilter mBloomFilter;
};
void addBigramsForWordPosition(
- const DictionaryStructureWithBufferPolicy *const structurePolicy, const int position);
+ const DictionaryStructureWithBufferPolicy *const structurePolicy,
+ const int *const prevWordsPtNodePos);
int readBigramProbabilityFromBinaryDictionary(
- const DictionaryStructureWithBufferPolicy *const structurePolicy, const int nodePos,
- const int nextWordPosition, const int unigramProbability);
+ const DictionaryStructureWithBufferPolicy *const structurePolicy,
+ const int *const prevWordsPtNodePos, const int nextWordPosition,
+ const int unigramProbability);
static const size_t MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP;
std::unordered_map<int, BigramMap> mBigramMaps;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
index ca79c18e5..2904b1e77 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
@@ -43,6 +43,10 @@ TrieMap::TrieMap() : mBuffer(MAX_BUFFER_SIZE) {
writeEntry(EMPTY_BITMAP_ENTRY, ROOT_BITMAP_ENTRY_INDEX);
}
+TrieMap::TrieMap(uint8_t *const buffer, const int bufferSize)
+ : mBuffer(buffer, bufferSize,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {}
+
void TrieMap::dump(const int from, const int to) const {
AKLOGI("BufSize: %d", mBuffer.getTailPosition());
for (int i = from; i < to; ++i) {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
index db278f5f1..8b33346e6 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
@@ -160,6 +160,8 @@ class TrieMap {
static const uint64_t MAX_VALUE;
TrieMap();
+ // Construct TrieMap using existing data in the memory region written by save().
+ TrieMap(uint8_t *const buffer, const int bufferSize);
void dump(const int from = 0, const int to = 0) const;
bool isNearSizeLimit() const {