diff options
36 files changed, 510 insertions, 432 deletions
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml index 1ffb8a32a..78217b01a 100644 --- a/java/res/layout/input_view.xml +++ b/java/res/layout/input_view.xml @@ -23,13 +23,8 @@ android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" + android:gravity="bottom|center_horizontal" > - <!-- The height of key_preview_backing view will automatically be determined by code. --> - <View - android:id="@+id/key_preview_backing" - android:layout_width="match_parent" - android:layout_height="0dp" /> - <!-- To ensure that key preview popup is correctly placed when the current system locale is one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. --> <com.android.inputmethod.latin.suggestions.SuggestionStripView @@ -37,17 +32,14 @@ android:layoutDirection="ltr" android:layout_width="match_parent" android:layout_height="@dimen/suggestions_strip_height" - android:gravity="center_vertical" android:paddingRight="@dimen/suggestions_strip_padding" android:paddingLeft="@dimen/suggestions_strip_padding" style="?attr/suggestionStripViewStyle" /> - <!-- To ensure that key preview popup is correctly placed when the current system locale is one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. --> <com.android.inputmethod.keyboard.MainKeyboardView android:id="@+id/keyboard_view" android:layoutDirection="ltr" - android:layout_alignParentBottom="true" - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_height="wrap_content" /> </com.android.inputmethod.latin.InputView> diff --git a/java/res/values-ka/strings-appname.xml b/java/res/values-ka/strings-appname.xml deleted file mode 100644 index 703c66aac..000000000 --- a/java/res/values-ka/strings-appname.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/* -** -** Copyright 2013, 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. -*/ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="english_ime_name" msgid="5940510615957428904">"Android-ის კლავიატურა (AOSP)"</string> - <string name="spell_checker_service_name" msgid="1254221805440242662">"Android-ის მართლწერის შემმოწმებელი (AOSP)"</string> - <string name="english_ime_settings" msgid="5760361067176802794">"Android-ის კლავიატურის პარამეტრები (AOSP)"</string> - <string name="android_spell_checker_settings" msgid="6123949487832861885">"Android-ის მართლწერის შემმოწმებლის პარამეტრები (AOSP)"</string> -</resources> diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 054c503d8..28eb58573 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -196,13 +196,14 @@ public class KeyboardView extends View { @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { - if (mKeyboard != null) { - // The main keyboard expands to the display width. - final int height = mKeyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom(); - setMeasuredDimension(widthMeasureSpec, height); - } else { + if (mKeyboard == null) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; } + // The main keyboard expands to the entire this {@link KeyboardView}. + final int width = mKeyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight(); + final int height = mKeyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom(); + setMeasuredDimension(width, height); } @Override diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index fa301b5a6..d0a4afd50 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -235,7 +235,7 @@ final public class BinaryDictionaryGetter { new BinaryDictInputOutput.ByteBufferWrapper(inStream.getChannel().map( FileChannel.MapMode.READ_ONLY, 0, f.length())); final int magic = buffer.readInt(); - if (magic != FormatSpec.VERSION_2_MAGIC_NUMBER) { + if (magic != FormatSpec.MAGIC_NUMBER) { return false; } final int formatVersion = buffer.readInt(); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 5c5b7b7c0..08a542965 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -31,7 +31,6 @@ import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.content.res.Resources; -import android.graphics.Rect; import android.inputmethodservice.InputMethodService; import android.media.AudioManager; import android.net.ConnectivityManager; @@ -51,7 +50,6 @@ import android.util.Printer; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.View; -import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; import android.view.inputmethod.CompletionInfo; @@ -150,8 +148,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private final Settings mSettings; - private View mExtractArea; - private View mKeyPreviewBackingView; + private View mInputView; + private int mInputViewMinHeight; private SuggestionStripView mSuggestionStripView; // Never null private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; @@ -660,17 +658,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return mKeyboardSwitcher.onCreateInputView(mIsHardwareAcceleratedDrawingEnabled); } + private void setInputViewMinHeight(final int minHeight) { + if (mInputView != null && mInputViewMinHeight != minHeight) { + mInputView.setMinimumHeight(minHeight); + mInputViewMinHeight = minHeight; + } + } + @Override - public void setInputView(final View view) { - super.setInputView(view); - mExtractArea = getWindow().getWindow().getDecorView() - .findViewById(android.R.id.extractArea); - mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing); - mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view); - if (mSuggestionStripView != null) - mSuggestionStripView.setListener(this, view); + public void setInputView(final View inputView) { + super.setInputView(inputView); + mInputView = inputView; + setInputViewMinHeight(0); + mSuggestionStripView = (SuggestionStripView)inputView.findViewById( + R.id.suggestion_strip_view); + if (mSuggestionStripView != null) { + mSuggestionStripView.setListener(this, inputView); + } if (LatinImeLogger.sVISUALDEBUG) { - mKeyPreviewBackingView.setBackgroundColor(0x10FF0000); + inputView.setBackgroundColor(0x10FF0000); } } @@ -1122,6 +1128,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSuggestionStripView.setVisibility( shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE); } + if (shouldShowSuggestions && mainKeyboardView != null) { + final int remainingHeight = getWindow().getWindow().getDecorView().getHeight() + - mainKeyboardView.getHeight() - mSuggestionStripView.getHeight(); + mSuggestionStripView.setMoreSuggestionsHeight(remainingHeight); + } } } @@ -1129,31 +1140,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); } - private int getAdjustedBackingViewHeight() { - final int currentHeight = mKeyPreviewBackingView.getHeight(); - if (currentHeight > 0) { - return currentHeight; - } - - final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); - if (mainKeyboardView == null) { - return 0; - } - final int keyboardHeight = mainKeyboardView.getHeight(); - final int suggestionsHeight = mSuggestionStripView.getHeight(); - final int displayHeight = getResources().getDisplayMetrics().heightPixels; - final Rect rect = new Rect(); - mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect); - final int notificationBarHeight = rect.top; - final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight - - keyboardHeight; - - final LayoutParams params = mKeyPreviewBackingView.getLayoutParams(); - params.height = mSuggestionStripView.setMoreSuggestionsHeight(remainingHeight); - mKeyPreviewBackingView.setLayoutParams(params); - return params.height; - } - @Override public void onComputeInsets(final InputMethodService.Insets outInsets) { super.onComputeInsets(outInsets); @@ -1161,32 +1147,30 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mainKeyboardView == null || mSuggestionStripView == null) { return; } - final int adjustedBackingHeight = getAdjustedBackingViewHeight(); - final boolean backingGone = (mKeyPreviewBackingView.getVisibility() == View.GONE); - final int backingHeight = backingGone ? 0 : adjustedBackingHeight; - // In fullscreen mode, the height of the extract area managed by InputMethodService should - // be considered. - // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. - final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0; - final int suggestionsHeight = (mSuggestionStripView.getVisibility() == View.GONE) ? 0 - : mSuggestionStripView.getHeight(); - final int extraHeight = extractHeight + backingHeight + suggestionsHeight; - int visibleTopY = extraHeight; + // This method is never called when in fullscreen mode. + // The contentTop is the top coordinate of the keyboard. The application behind will be + // resized/panned above this coordibnate to be able to show an input field. + final int contentTop = mInputView.getHeight() - mainKeyboardView.getHeight(); + final int suggestionsHeight = (mSuggestionStripView.getVisibility() == View.VISIBLE) + ? mSuggestionStripView.getHeight() : 0; + // The visibleTop is the top coordinates of the visible part of this IME. The application + // behind will never be resized, but may be panned or scrolled. + final int visibleTop = mainKeyboardView.isShowingMoreKeysPanel() ? 0 + : contentTop - suggestionsHeight; + outInsets.contentTopInsets = contentTop; + outInsets.visibleTopInsets = visibleTop; // Need to set touchable region only if input view is being shown if (mainKeyboardView.isShown()) { - if (mSuggestionStripView.getVisibility() == View.VISIBLE) { - visibleTopY -= suggestionsHeight; - } - final int touchY = mainKeyboardView.isShowingMoreKeysPanel() ? 0 : visibleTopY; - final int touchWidth = mainKeyboardView.getWidth(); - final int touchHeight = mainKeyboardView.getHeight() + extraHeight + final int touchLeft = 0; + final int touchTop = visibleTop; + final int touchRight = touchLeft + mainKeyboardView.getWidth(); + final int touchBottom = contentTop + mainKeyboardView.getHeight() // Extend touchable region below the keyboard. + EXTENDED_TOUCHABLE_REGION_HEIGHT; + // The touch event on touchableRegion will be delivered to this IME. + outInsets.touchableRegion.set(touchLeft, touchTop, touchRight, touchBottom); outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; - outInsets.touchableRegion.set(0, touchY, touchWidth, touchHeight); } - outInsets.contentTopInsets = visibleTopY; - outInsets.visibleTopInsets = visibleTopY; } @Override @@ -1209,11 +1193,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void updateFullscreenMode() { super.updateFullscreenMode(); - - if (mKeyPreviewBackingView == null) return; - // In fullscreen mode, no need to have extra space to show the key preview. - // If not, we should have extra space above the keyboard to show the key preview. - mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE); + if (!isFullscreenMode()) { + // Expand the input view to cover entire display to be able to show key previews and + // more suggestions view that may be displayed above the keyboard. + setInputViewMinHeight(getResources().getDisplayMetrics().heightPixels); + } } // This will reset the whole input state to the starting state. It will clear diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 1b187d85d..e2fa0231d 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -1210,49 +1210,38 @@ public final class BinaryDictInputOutput { ByteArrayOutputStream headerBuffer = new ByteArrayOutputStream(256); // The magic number in big-endian order. - if (version >= FormatSpec.FIRST_VERSION_WITH_HEADER_SIZE) { - // Magic number for version 2+. - headerBuffer.write((byte) (0xFF & (FormatSpec.VERSION_2_MAGIC_NUMBER >> 24))); - headerBuffer.write((byte) (0xFF & (FormatSpec.VERSION_2_MAGIC_NUMBER >> 16))); - headerBuffer.write((byte) (0xFF & (FormatSpec.VERSION_2_MAGIC_NUMBER >> 8))); - headerBuffer.write((byte) (0xFF & FormatSpec.VERSION_2_MAGIC_NUMBER)); - // Dictionary version. - headerBuffer.write((byte) (0xFF & (version >> 8))); - headerBuffer.write((byte) (0xFF & version)); - } else { - // Magic number for version 1. - headerBuffer.write((byte) (0xFF & (FormatSpec.VERSION_1_MAGIC_NUMBER >> 8))); - headerBuffer.write((byte) (0xFF & FormatSpec.VERSION_1_MAGIC_NUMBER)); - // Dictionary version. - headerBuffer.write((byte) (0xFF & version)); - } + // Magic number for all versions. + headerBuffer.write((byte) (0xFF & (FormatSpec.MAGIC_NUMBER >> 24))); + headerBuffer.write((byte) (0xFF & (FormatSpec.MAGIC_NUMBER >> 16))); + headerBuffer.write((byte) (0xFF & (FormatSpec.MAGIC_NUMBER >> 8))); + headerBuffer.write((byte) (0xFF & FormatSpec.MAGIC_NUMBER)); + // Dictionary version. + headerBuffer.write((byte) (0xFF & (version >> 8))); + headerBuffer.write((byte) (0xFF & version)); + // Options flags final int options = makeOptionsValue(dict, formatOptions); headerBuffer.write((byte) (0xFF & (options >> 8))); headerBuffer.write((byte) (0xFF & options)); - if (version >= FormatSpec.FIRST_VERSION_WITH_HEADER_SIZE) { - final int headerSizeOffset = headerBuffer.size(); - // Placeholder to be written later with header size. - for (int i = 0; i < 4; ++i) { - headerBuffer.write(0); - } - // Write out the options. - for (final String key : dict.mOptions.mAttributes.keySet()) { - final String value = dict.mOptions.mAttributes.get(key); - CharEncoding.writeString(headerBuffer, key); - CharEncoding.writeString(headerBuffer, value); - } - final int size = headerBuffer.size(); - final byte[] bytes = headerBuffer.toByteArray(); - // Write out the header size. - bytes[headerSizeOffset] = (byte) (0xFF & (size >> 24)); - bytes[headerSizeOffset + 1] = (byte) (0xFF & (size >> 16)); - bytes[headerSizeOffset + 2] = (byte) (0xFF & (size >> 8)); - bytes[headerSizeOffset + 3] = (byte) (0xFF & (size >> 0)); - destination.write(bytes); - } else { - headerBuffer.writeTo(destination); - } + final int headerSizeOffset = headerBuffer.size(); + // Placeholder to be written later with header size. + for (int i = 0; i < 4; ++i) { + headerBuffer.write(0); + } + // Write out the options. + for (final String key : dict.mOptions.mAttributes.keySet()) { + final String value = dict.mOptions.mAttributes.get(key); + CharEncoding.writeString(headerBuffer, key); + CharEncoding.writeString(headerBuffer, value); + } + final int size = headerBuffer.size(); + final byte[] bytes = headerBuffer.toByteArray(); + // Write out the header size. + bytes[headerSizeOffset] = (byte) (0xFF & (size >> 24)); + bytes[headerSizeOffset + 1] = (byte) (0xFF & (size >> 16)); + bytes[headerSizeOffset + 2] = (byte) (0xFF & (size >> 8)); + bytes[headerSizeOffset + 3] = (byte) (0xFF & (size >> 0)); + destination.write(bytes); headerBuffer.close(); @@ -1658,10 +1647,8 @@ public final class BinaryDictInputOutput { */ private static int getFormatVersion(final FusionDictionaryBufferInterface buffer) throws IOException { - final int magic_v1 = buffer.readUnsignedShort(); - if (FormatSpec.VERSION_1_MAGIC_NUMBER == magic_v1) return buffer.readUnsignedByte(); - final int magic_v2 = (magic_v1 << 16) + buffer.readUnsignedShort(); - if (FormatSpec.VERSION_2_MAGIC_NUMBER == magic_v2) return buffer.readUnsignedShort(); + final int magic = buffer.readInt(); + if (FormatSpec.MAGIC_NUMBER == magic) return buffer.readUnsignedShort(); return FormatSpec.NOT_A_VERSION_NUMBER; } @@ -1695,13 +1682,9 @@ public final class BinaryDictInputOutput { final HashMap<String, String> attributes = new HashMap<String, String>(); final int headerSize; - if (version < FormatSpec.FIRST_VERSION_WITH_HEADER_SIZE) { - headerSize = buffer.position(); - } else { - headerSize = buffer.readInt(); - populateOptions(buffer, headerSize, attributes); - buffer.position(headerSize); - } + headerSize = buffer.readInt(); + populateOptions(buffer, headerSize, attributes); + buffer.position(headerSize); if (headerSize < 0) { throw new UnsupportedFormatException("header size can't be negative."); diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 46266aa50..2bb5d8b6e 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -26,6 +26,40 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions public final class FormatSpec { /* + * File header layout is as follows: + * + * v | + * e | MAGIC_NUMBER + version of the file format, 2 bytes. + * r | + * sion + * + * o | + * p | not used 4 bits + * t | has bigrams ? 1 bit, 1 = yes, 0 = no : CONTAINS_BIGRAMS_FLAG + * i | FRENCH_LIGATURE_PROCESSING_FLAG + * o | supports dynamic updates ? 1 bit, 1 = yes, 0 = no : SUPPORTS_DYNAMIC_UPDATE + * n | GERMAN_UMLAUT_PROCESSING_FLAG + * f | + * lags + * + * h | + * e | size of the file header, 4bytes + * a | including the size of the magic number, the option flags and the header size + * d | + * ersize + * + * | attributes list + * + * attributes list is: + * <key> = | string of characters at the char format described below, with the terminator used + * | to signal the end of the string. + * <value> = | string of characters at the char format described below, with the terminator used + * | to signal the end of the string. + * if the size of already read < headersize, goto key. + * + */ + + /* * Array of Node(FusionDictionary.Node) layout is as follows: * * g | @@ -151,12 +185,10 @@ public final class FormatSpec { * if (FLAG_ATTRIBUTE_HAS_NEXT goto flags */ - static final int VERSION_1_MAGIC_NUMBER = 0x78B1; - public static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; - static final int MINIMUM_SUPPORTED_VERSION = 1; + public static final int MAGIC_NUMBER = 0x9BC13AFE; + static final int MINIMUM_SUPPORTED_VERSION = 2; static final int MAXIMUM_SUPPORTED_VERSION = 3; static final int NOT_A_VERSION_NUMBER = -1; - static final int FIRST_VERSION_WITH_HEADER_SIZE = 2; static final int FIRST_VERSION_WITH_DYNAMIC_UPDATE = 3; // These options need to be the same numeric values as the one in the native reading code. diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 1dd04fc4d..bcf64a8e8 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -177,20 +177,9 @@ final class SuggestionStripLayoutHelper { return mMaxMoreSuggestionsRow; } - private int getMoreSuggestionsHeight() { - return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap; - } - - public int setMoreSuggestionsHeight(final int remainingHeight) { - final int currentHeight = getMoreSuggestionsHeight(); - if (currentHeight <= remainingHeight) { - return currentHeight; - } - + public void setMoreSuggestionsHeight(final int remainingHeight) { mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap) / mMoreSuggestionsRowHeight; - final int newHeight = getMoreSuggestionsHeight(); - return newHeight; } private static Drawable getMoreSuggestionsHint(final Resources res, final float textSize, diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index a8a14a825..2644f3c9c 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -135,8 +135,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } } - public int setMoreSuggestionsHeight(final int remainingHeight) { - return mLayoutHelper.setMoreSuggestionsHeight(remainingHeight); + public void setMoreSuggestionsHeight(final int remainingHeight) { + mLayoutHelper.setMoreSuggestionsHeight(remainingHeight); } public boolean isShowingAddToDictionaryHint() { diff --git a/java/src/com/android/inputmethod/latin/utils/UserLogRingCharBuffer.java b/java/src/com/android/inputmethod/latin/utils/UserLogRingCharBuffer.java index 161386e2e..a75d353c9 100644 --- a/java/src/com/android/inputmethod/latin/utils/UserLogRingCharBuffer.java +++ b/java/src/com/android/inputmethod/latin/utils/UserLogRingCharBuffer.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin.utils; import android.inputmethodservice.InputMethodService; import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.settings.Settings; public final class UserLogRingCharBuffer { @@ -64,6 +65,9 @@ public final class UserLogRingCharBuffer { if (!mEnabled) { return; } + if (LatinImeLogger.sUsabilityStudy) { + UsabilityStudyLogUtils.getInstance().writeChar(c, x, y); + } mCharBuf[mEnd] = c; mXBuf[mEnd] = x; mYBuf[mEnd] = y; diff --git a/native/jni/Android.mk b/native/jni/Android.mk index e14cf5a71..4786ef6c7 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -71,6 +71,7 @@ LATIN_IME_CORE_SRC_FILES := \ suggest/core/policy/weighting.cpp \ suggest/core/session/dic_traverse_session.cpp \ $(addprefix suggest/policyimpl/dictionary/, \ + dictionary_structure_with_buffer_policy_factory.cpp \ dynamic_patricia_trie_node_reader.cpp \ dynamic_patricia_trie_policy.cpp \ dynamic_patricia_trie_reading_utils.cpp \ diff --git a/native/jni/src/suggest/core/dicnode/dic_node_proximity_filter.h b/native/jni/src/suggest/core/dicnode/dic_node_proximity_filter.h index 1a39f2ef3..c7ab571de 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node_proximity_filter.h +++ b/native/jni/src/suggest/core/dicnode/dic_node_proximity_filter.h @@ -20,11 +20,11 @@ #include "defines.h" #include "suggest/core/layout/proximity_info_state.h" #include "suggest/core/layout/proximity_info_utils.h" -#include "suggest/core/policy/dictionary_structure_policy.h" +#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h" namespace latinime { -class DicNodeProximityFilter : public DictionaryStructurePolicy::NodeFilter { +class DicNodeProximityFilter : public DictionaryStructureWithBufferPolicy::NodeFilter { public: DicNodeProximityFilter(const ProximityInfoState *const pInfoState, const int pointIndex, const bool exactOnly) 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 6b4ef2fea..4ff4bc2e4 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp +++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp @@ -24,7 +24,7 @@ #include "suggest/core/dictionary/binary_dictionary_info.h" #include "suggest/core/dictionary/multi_bigram_map.h" #include "suggest/core/dictionary/probability_utils.h" -#include "suggest/core/policy/dictionary_structure_policy.h" +#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h" #include "utils/char_utils.h" namespace latinime { @@ -83,7 +83,7 @@ namespace latinime { DicNodeUtils::createAndGetPassingChildNode(dicNode, &childrenFilter, childDicNodes); } else { binaryDictionaryInfo->getStructurePolicy()->createAndGetAllChildNodes(dicNode, - binaryDictionaryInfo, &childrenFilter, childDicNodes); + &childrenFilter, childDicNodes); } } @@ -118,8 +118,8 @@ namespace latinime { return ProbabilityUtils::backoff(unigramProbability); } if (multiBigramMap) { - return multiBigramMap->getBigramProbability( - binaryDictionaryInfo, prevWordPos, wordPos, unigramProbability); + return multiBigramMap->getBigramProbability(binaryDictionaryInfo->getStructurePolicy(), + prevWordPos, wordPos, unigramProbability); } return ProbabilityUtils::backoff(unigramProbability); } diff --git a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp index 3751ae500..fdaa562e5 100644 --- a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp +++ b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp @@ -112,13 +112,14 @@ int BigramDictionary::getPredictions(const int *prevWord, const int prevWordLeng int bigramCount = 0; int unigramProbability = 0; int bigramBuffer[MAX_WORD_LENGTH]; - BinaryDictionaryBigramsIterator bigramsIt(mBinaryDictionaryInfo, pos); + const DictionaryStructureWithBufferPolicy *const structurePolicy = + mBinaryDictionaryInfo->getStructurePolicy(); + BinaryDictionaryBigramsIterator bigramsIt(structurePolicy->getBigramsStructurePolicy(), pos); while (bigramsIt.hasNext()) { bigramsIt.next(); - const int length = mBinaryDictionaryInfo->getStructurePolicy()-> - getCodePointsAndProbabilityAndReturnCodePointCount( - mBinaryDictionaryInfo, bigramsIt.getBigramPos(), MAX_WORD_LENGTH, - bigramBuffer, &unigramProbability); + const int length = structurePolicy-> + getCodePointsAndProbabilityAndReturnCodePointCount(bigramsIt.getBigramPos(), + MAX_WORD_LENGTH, bigramBuffer, &unigramProbability); // Due to space constraints, the probability for bigrams is approximate - the lower the // unigram probability, the worse the precision. The theoritical maximum error in // resulting probability is 8 - although in the practice it's never bigger than 3 or 4 @@ -138,11 +139,12 @@ int BigramDictionary::getPredictions(const int *prevWord, const int prevWordLeng int BigramDictionary::getBigramListPositionForWord(const int *prevWord, const int prevWordLength, const bool forceLowerCaseSearch) const { if (0 >= prevWordLength) return NOT_A_DICT_POS; - int pos = mBinaryDictionaryInfo->getStructurePolicy()->getTerminalNodePositionOfWord( - mBinaryDictionaryInfo, prevWord, prevWordLength, forceLowerCaseSearch); + const DictionaryStructureWithBufferPolicy *const structurePolicy = + mBinaryDictionaryInfo->getStructurePolicy(); + int pos = structurePolicy->getTerminalNodePositionOfWord(prevWord, prevWordLength, + forceLowerCaseSearch); if (NOT_A_VALID_WORD_POS == pos) return NOT_A_DICT_POS; - return mBinaryDictionaryInfo->getStructurePolicy()->getBigramsPositionOfNode( - mBinaryDictionaryInfo, pos); + return structurePolicy->getBigramsPositionOfNode(pos); } bool BigramDictionary::isValidBigram(const int *word0, int length0, const int *word1, @@ -150,11 +152,13 @@ bool BigramDictionary::isValidBigram(const int *word0, int length0, const int *w int pos = getBigramListPositionForWord(word0, length0, false /* forceLowerCaseSearch */); // getBigramListPositionForWord returns 0 if this word isn't in the dictionary or has no bigrams if (NOT_A_DICT_POS == pos) return false; - int nextWordPos = mBinaryDictionaryInfo->getStructurePolicy()->getTerminalNodePositionOfWord( - mBinaryDictionaryInfo, word1, length1, false /* forceLowerCaseSearch */); + const DictionaryStructureWithBufferPolicy *const structurePolicy = + mBinaryDictionaryInfo->getStructurePolicy(); + int nextWordPos = structurePolicy->getTerminalNodePositionOfWord(word1, length1, + false /* forceLowerCaseSearch */); if (NOT_A_VALID_WORD_POS == nextWordPos) return false; - BinaryDictionaryBigramsIterator bigramsIt(mBinaryDictionaryInfo, pos); + BinaryDictionaryBigramsIterator bigramsIt(structurePolicy->getBigramsStructurePolicy(), pos); while (bigramsIt.hasNext()) { bigramsIt.next(); if (bigramsIt.getBigramPos() == nextWordPos) { diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_bigrams_iterator.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_bigrams_iterator.h index 8cbb12998..d16ac47fe 100644 --- a/native/jni/src/suggest/core/dictionary/binary_dictionary_bigrams_iterator.h +++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_bigrams_iterator.h @@ -18,51 +18,41 @@ #define LATINIME_BINARY_DICTIONARY_BIGRAMS_ITERATOR_H #include "defines.h" -#include "suggest/core/dictionary/binary_dictionary_info.h" -#include "suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h" +#include "suggest/core/policy/dictionary_bigrams_structure_policy.h" namespace latinime { class BinaryDictionaryBigramsIterator { public: BinaryDictionaryBigramsIterator( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int pos) - : mBinaryDictionaryInfo(binaryDictionaryInfo), mPos(pos), mBigramFlags(0), - mBigramPos(NOT_A_DICT_POS), mHasNext(pos != NOT_A_DICT_POS) {} + const DictionaryBigramsStructurePolicy *const bigramsStructurePolicy, const int pos) + : mBigramsStructurePolicy(bigramsStructurePolicy), mPos(pos), + mBigramPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY), + mHasNext(pos != NOT_A_DICT_POS) {} AK_FORCE_INLINE bool hasNext() const { return mHasNext; } AK_FORCE_INLINE void next() { - mBigramFlags = BinaryDictionaryTerminalAttributesReadingUtils::getFlagsAndForwardPointer( - mBinaryDictionaryInfo, &mPos); - mBigramPos = - BinaryDictionaryTerminalAttributesReadingUtils::getBigramAddressAndForwardPointer( - mBinaryDictionaryInfo, mBigramFlags, &mPos); - mHasNext = BinaryDictionaryTerminalAttributesReadingUtils::hasNext(mBigramFlags); + mBigramsStructurePolicy->getNextBigram(&mBigramPos, &mProbability, &mHasNext, &mPos); } AK_FORCE_INLINE int getProbability() const { - return BinaryDictionaryTerminalAttributesReadingUtils::getProbabilityFromFlags( - mBigramFlags); + return mProbability; } AK_FORCE_INLINE int getBigramPos() const { return mBigramPos; } - AK_FORCE_INLINE int getFlags() const { - return mBigramFlags; - } - private: DISALLOW_COPY_AND_ASSIGN(BinaryDictionaryBigramsIterator); - const BinaryDictionaryInfo *const mBinaryDictionaryInfo; + const DictionaryBigramsStructurePolicy *const mBigramsStructurePolicy; int mPos; - BinaryDictionaryTerminalAttributesReadingUtils::BigramFlags mBigramFlags; int mBigramPos; + int mProbability; bool mHasNext; }; } // namespace latinime diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h index cbea18f90..c694c6a3a 100644 --- a/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h +++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h @@ -23,7 +23,7 @@ #include "jni.h" #include "suggest/core/dictionary/binary_dictionary_format_utils.h" #include "suggest/core/dictionary/binary_dictionary_header.h" -#include "suggest/policyimpl/dictionary/dictionary_structure_policy_factory.h" +#include "suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h" #include "utils/log_utils.h" namespace latinime { @@ -37,11 +37,16 @@ class BinaryDictionaryInfo { mDictionaryFormat(BinaryDictionaryFormatUtils::detectFormatVersion( mDictBuf, mDictSize)), mDictionaryHeader(this), mDictRoot(mDictBuf + mDictionaryHeader.getSize()), - mStructurePolicy(DictionaryStructurePolicyFactory::getDictionaryStructurePolicy( - mDictionaryFormat)) { + // TODO: Remove. + mStructurePolicy(DictionaryStructureWithBufferPolicyFactory + ::newDictionaryStructurePolicy(this)) { logDictionaryInfo(env); } + ~BinaryDictionaryInfo() { + delete mStructurePolicy; + } + AK_FORCE_INLINE const uint8_t *getDictBuf() const { return mDictBuf; } @@ -66,6 +71,7 @@ class BinaryDictionaryInfo { return mDictionaryFormat; } + // TODO: Move to DictionaryStructurePolicy. AK_FORCE_INLINE const BinaryDictionaryHeader *getHeader() const { return &mDictionaryHeader; } @@ -76,7 +82,8 @@ class BinaryDictionaryInfo { return mIsUpdatable && isUpdatableDictionaryFormat; } - AK_FORCE_INLINE const DictionaryStructurePolicy *getStructurePolicy() const { + // TODO: remove + AK_FORCE_INLINE const DictionaryStructureWithBufferPolicy *getStructurePolicy() const { return mStructurePolicy; } @@ -89,9 +96,12 @@ class BinaryDictionaryInfo { const int mDictBufOffset; const bool mIsUpdatable; const BinaryDictionaryFormatUtils::FORMAT_VERSION mDictionaryFormat; + // TODO: Move BinaryDictionaryHeader to policyimpl and introduce dedicated API to the + // DictionaryStructurePolicy. const BinaryDictionaryHeader mDictionaryHeader; const uint8_t *const mDictRoot; - const DictionaryStructurePolicy *const mStructurePolicy; + // TODO: remove + const DictionaryStructureWithBufferPolicy *const mStructurePolicy; AK_FORCE_INLINE void logDictionaryInfo(JNIEnv *const env) const { const int BUFFER_SIZE = 16; diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.cpp b/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.cpp index 20b77b3b2..9e7d7a391 100644 --- a/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.cpp +++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.cpp @@ -16,7 +16,6 @@ #include "suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h" -#include "suggest/core/dictionary/binary_dictionary_info.h" #include "suggest/core/dictionary/byte_array_utils.h" namespace latinime { @@ -38,22 +37,19 @@ const int TaUtils::SHORTCUT_LIST_SIZE_FIELD_SIZE = 2; const int TaUtils::WHITELIST_SHORTCUT_PROBABILITY = 15; /* static */ int TaUtils::getBigramAddressAndForwardPointer( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const TerminalAttributeFlags flags, + const uint8_t *const dictRoot, const TerminalAttributeFlags flags, int *const pos) { int offset = 0; const int origin = *pos; switch (MASK_ATTRIBUTE_ADDRESS_TYPE & flags) { case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE: - offset = ByteArrayUtils::readUint8AndAdvancePosition( - binaryDictionaryInfo->getDictRoot(), pos); + offset = ByteArrayUtils::readUint8AndAdvancePosition(dictRoot, pos); break; case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES: - offset = ByteArrayUtils::readUint16AndAdvancePosition( - binaryDictionaryInfo->getDictRoot(), pos); + offset = ByteArrayUtils::readUint16AndAdvancePosition(dictRoot, pos); break; case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES: - offset = ByteArrayUtils::readUint24AndAdvancePosition( - binaryDictionaryInfo->getDictRoot(), pos); + offset = ByteArrayUtils::readUint24AndAdvancePosition(dictRoot, pos); break; } if (isOffsetNegative(flags)) { diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h index 375fc7dff..e1e3e1618 100644 --- a/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h +++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h @@ -32,9 +32,8 @@ class BinaryDictionaryTerminalAttributesReadingUtils { typedef TerminalAttributeFlags ShortcutFlags; static AK_FORCE_INLINE TerminalAttributeFlags getFlagsAndForwardPointer( - const BinaryDictionaryInfo *const binaryDictionaryInfo, int *const pos) { - return ByteArrayUtils::readUint8AndAdvancePosition( - binaryDictionaryInfo->getDictRoot(), pos); + const uint8_t *const dictRoot, int *const pos) { + return ByteArrayUtils::readUint8AndAdvancePosition(dictRoot, pos); } static AK_FORCE_INLINE int getProbabilityFromFlags(const TerminalAttributeFlags flags) { @@ -47,18 +46,17 @@ class BinaryDictionaryTerminalAttributesReadingUtils { // Bigrams reading methods static AK_FORCE_INLINE void skipExistingBigrams( - const BinaryDictionaryInfo *const binaryDictionaryInfo, int *const pos) { - BigramFlags flags = getFlagsAndForwardPointer(binaryDictionaryInfo, pos); + const uint8_t *const dictRoot, int *const pos) { + BigramFlags flags = getFlagsAndForwardPointer(dictRoot, pos); while (hasNext(flags)) { *pos += attributeAddressSize(flags); - flags = getFlagsAndForwardPointer(binaryDictionaryInfo, pos); + flags = getFlagsAndForwardPointer(dictRoot, pos); } *pos += attributeAddressSize(flags); } static int getBigramAddressAndForwardPointer( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const BigramFlags flags, - int *const pos); + const uint8_t *const dictRoot, const BigramFlags flags, int *const pos); // Shortcuts reading methods // This method returns the size of the shortcut list region excluding the shortcut list size diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp index 4a9e38fe8..891b80331 100644 --- a/native/jni/src/suggest/core/dictionary/dictionary.cpp +++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp @@ -83,14 +83,14 @@ int Dictionary::getBigrams(const int *word, int length, int *outWords, int *freq } int Dictionary::getProbability(const int *word, int length) const { - const DictionaryStructurePolicy *const structurePolicy = + const DictionaryStructureWithBufferPolicy *const structurePolicy = mBinaryDictionaryInfo.getStructurePolicy(); - int pos = structurePolicy->getTerminalNodePositionOfWord(&mBinaryDictionaryInfo, word, length, + int pos = structurePolicy->getTerminalNodePositionOfWord(word, length, false /* forceLowerCaseSearch */); if (NOT_A_VALID_WORD_POS == pos) { return NOT_A_PROBABILITY; } - return structurePolicy->getUnigramProbability(&mBinaryDictionaryInfo, pos); + return structurePolicy->getUnigramProbability(pos); } bool Dictionary::isValidBigram(const int *word0, int length0, const int *word1, int length1) const { 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 d5eafe1bf..97d4cd161 100644 --- a/native/jni/src/suggest/core/dictionary/multi_bigram_map.h +++ b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h @@ -21,9 +21,9 @@ #include "defines.h" #include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h" -#include "suggest/core/dictionary/binary_dictionary_info.h" #include "suggest/core/dictionary/bloom_filter.h" #include "suggest/core/dictionary/probability_utils.h" +#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h" #include "utils/hash_map_compat.h" namespace latinime { @@ -38,7 +38,7 @@ 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 BinaryDictionaryInfo *const binaryDictionaryInfo, + int getBigramProbability(const DictionaryStructureWithBufferPolicy *const structurePolicy, const int wordPosition, const int nextWordPosition, const int unigramProbability) { hash_map_compat<int, BigramMap>::const_iterator mapPosition = mBigramMaps.find(wordPosition); @@ -46,12 +46,12 @@ class MultiBigramMap { return mapPosition->second.getBigramProbability(nextWordPosition, unigramProbability); } if (mBigramMaps.size() < MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP) { - addBigramsForWordPosition(binaryDictionaryInfo, wordPosition); + addBigramsForWordPosition(structurePolicy, wordPosition); return mBigramMaps[wordPosition].getBigramProbability( nextWordPosition, unigramProbability); } - return readBigramProbabilityFromBinaryDictionary(binaryDictionaryInfo, - wordPosition, nextWordPosition, unigramProbability); + return readBigramProbabilityFromBinaryDictionary(structurePolicy, wordPosition, + nextWordPosition, unigramProbability); } void clear() { @@ -66,10 +66,11 @@ class MultiBigramMap { BigramMap() : mBigramMap(DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP), mBloomFilter() {} ~BigramMap() {} - void init(const BinaryDictionaryInfo *const binaryDictionaryInfo, const int nodePos) { - const int bigramsListPos = binaryDictionaryInfo->getStructurePolicy()-> - getBigramsPositionOfNode(binaryDictionaryInfo, nodePos); - BinaryDictionaryBigramsIterator bigramsIt(binaryDictionaryInfo, bigramsListPos); + void init(const DictionaryStructureWithBufferPolicy *const structurePolicy, + const int nodePos) { + const int bigramsListPos = structurePolicy->getBigramsPositionOfNode(nodePos); + BinaryDictionaryBigramsIterator bigramsIt(structurePolicy->getBigramsStructurePolicy(), + bigramsListPos); while (bigramsIt.hasNext()) { bigramsIt.next(); mBigramMap[bigramsIt.getBigramPos()] = bigramsIt.getProbability(); @@ -100,16 +101,16 @@ class MultiBigramMap { }; AK_FORCE_INLINE void addBigramsForWordPosition( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int position) { - mBigramMaps[position].init(binaryDictionaryInfo, position); + const DictionaryStructureWithBufferPolicy *const structurePolicy, const int position) { + mBigramMaps[position].init(structurePolicy, position); } AK_FORCE_INLINE int readBigramProbabilityFromBinaryDictionary( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int nodePos, + const DictionaryStructureWithBufferPolicy *const structurePolicy, const int nodePos, const int nextWordPosition, const int unigramProbability) { - const int bigramsListPos = binaryDictionaryInfo->getStructurePolicy()-> - getBigramsPositionOfNode(binaryDictionaryInfo, nodePos); - BinaryDictionaryBigramsIterator bigramsIt(binaryDictionaryInfo, bigramsListPos); + const int bigramsListPos = structurePolicy->getBigramsPositionOfNode(nodePos); + BinaryDictionaryBigramsIterator bigramsIt(structurePolicy->getBigramsStructurePolicy(), + bigramsListPos); while (bigramsIt.hasNext()) { bigramsIt.next(); if (bigramsIt.getBigramPos() == nextWordPosition) { diff --git a/native/jni/src/suggest/core/dictionary/terminal_attributes.h b/native/jni/src/suggest/core/dictionary/terminal_attributes.h index 0da6504eb..c40a3bb59 100644 --- a/native/jni/src/suggest/core/dictionary/terminal_attributes.h +++ b/native/jni/src/suggest/core/dictionary/terminal_attributes.h @@ -49,7 +49,7 @@ class TerminalAttributes { bool *const outIsWhitelist) { const BinaryDictionaryTerminalAttributesReadingUtils::ShortcutFlags flags = BinaryDictionaryTerminalAttributesReadingUtils::getFlagsAndForwardPointer( - mBinaryDictionaryInfo, &mPos); + mBinaryDictionaryInfo->getDictRoot(), &mPos); mHasNextShortcutTarget = BinaryDictionaryTerminalAttributesReadingUtils::hasNext(flags); if (outIsWhitelist) { diff --git a/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h b/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h new file mode 100644 index 000000000..661ef1b1a --- /dev/null +++ b/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013, 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. + */ + +#ifndef LATINIME_DICTIONARY_BIGRAMS_STRUCTURE_POLICY_H +#define LATINIME_DICTIONARY_BIGRAMS_STRUCTURE_POLICY_H + +#include "defines.h" + +namespace latinime { + +/* + * This class abstracts structure of bigrams. + */ +class DictionaryBigramsStructurePolicy { + public: + virtual ~DictionaryBigramsStructurePolicy() {} + + virtual void getNextBigram(int *const outBigramPos, int *const outProbability, + bool *const outHasNext, int *const pos) const = 0; + virtual void skipAllBigrams(int *const pos) const = 0; + + protected: + DictionaryBigramsStructurePolicy() {} + + private: + DISALLOW_COPY_AND_ASSIGN(DictionaryBigramsStructurePolicy); +}; +} // namespace latinime +#endif /* LATINIME_DICTIONARY_BIGRAMS_STRUCTURE_POLICY_H */ diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h index cc14c982c..d83d1e390 100644 --- a/native/jni/src/suggest/core/policy/dictionary_structure_policy.h +++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h @@ -21,15 +21,15 @@ namespace latinime { -class BinaryDictionaryInfo; class DicNode; class DicNodeVector; +class DictionaryBigramsStructurePolicy; /* * This class abstracts structure of dictionaries. * Implement this policy to support additional dictionaries. */ -class DictionaryStructurePolicy { +class DictionaryStructureWithBufferPolicy { public: // This provides a filtering method for filtering new node. class NodeFilter { @@ -44,36 +44,33 @@ class DictionaryStructurePolicy { DISALLOW_COPY_AND_ASSIGN(NodeFilter); }; + virtual ~DictionaryStructureWithBufferPolicy() {} + virtual int getRootPosition() const = 0; virtual void createAndGetAllChildNodes(const DicNode *const dicNode, - const BinaryDictionaryInfo *const binaryDictionaryInfo, const NodeFilter *const nodeFilter, DicNodeVector *const childDicNodes) const = 0; virtual int getCodePointsAndProbabilityAndReturnCodePointCount( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int nodePos, const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) const = 0; - virtual int getTerminalNodePositionOfWord( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int *const inWord, + virtual int getTerminalNodePositionOfWord(const int *const inWord, const int length, const bool forceLowerCaseSearch) const = 0; - virtual int getUnigramProbability(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const = 0; + virtual int getUnigramProbability(const int nodePos) const = 0; + + virtual int getShortcutPositionOfNode(const int nodePos) const = 0; - virtual int getShortcutPositionOfNode(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const = 0; + virtual int getBigramsPositionOfNode(const int nodePos) const = 0; - virtual int getBigramsPositionOfNode(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const = 0; + virtual const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const = 0; protected: - DictionaryStructurePolicy() {} - virtual ~DictionaryStructurePolicy() {} + DictionaryStructureWithBufferPolicy() {} private: - DISALLOW_COPY_AND_ASSIGN(DictionaryStructurePolicy); + DISALLOW_COPY_AND_ASSIGN(DictionaryStructureWithBufferPolicy); }; } // namespace latinime #endif /* LATINIME_DICTIONARY_STRUCTURE_POLICY_H */ diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp index 7651b19a0..11a147bda 100644 --- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp +++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp @@ -37,12 +37,12 @@ void DicTraverseSession::init(const Dictionary *const dictionary, const int *pre } // TODO: merge following similar calls to getTerminalPosition into one case-insensitive call. mPrevWordPos = binaryDictionaryInfo->getStructurePolicy()->getTerminalNodePositionOfWord( - binaryDictionaryInfo, prevWord, prevWordLength, false /* forceLowerCaseSearch */); + prevWord, prevWordLength, false /* forceLowerCaseSearch */); if (mPrevWordPos == NOT_A_VALID_WORD_POS) { // Check bigrams for lower-cased previous word if original was not found. Useful for // auto-capitalized words like "The [current_word]". mPrevWordPos = binaryDictionaryInfo->getStructurePolicy()->getTerminalNodePositionOfWord( - binaryDictionaryInfo, prevWord, prevWordLength, true /* forceLowerCaseSearch */); + prevWord, prevWordLength, true /* forceLowerCaseSearch */); } } diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h index de57e041a..5c4cef02d 100644 --- a/native/jni/src/suggest/core/session/dic_traverse_session.h +++ b/native/jni/src/suggest/core/session/dic_traverse_session.h @@ -75,7 +75,7 @@ class DicTraverseSession { const int maxPointerCount); void resetCache(const int nextActiveCacheSize, const int maxWords); - // TODO: Remove + // TODO: Use DictionaryStructurePolicy instead of BinaryDictionaryInfo. const BinaryDictionaryInfo *getBinaryDictionaryInfo() const; //-------------------- diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp index 9376d7b93..f28efd526 100644 --- a/native/jni/src/suggest/core/suggest.cpp +++ b/native/jni/src/suggest/core/suggest.cpp @@ -215,7 +215,7 @@ int Suggest::outputSuggestions(DicTraverseSession *traverseSession, int *frequen traverseSession->getBinaryDictionaryInfo(); const TerminalAttributes terminalAttributes(traverseSession->getBinaryDictionaryInfo(), binaryDictionaryInfo->getStructurePolicy()->getShortcutPositionOfNode( - binaryDictionaryInfo, terminalDicNode->getPos())); + terminalDicNode->getPos())); // Shortcut is not supported for multiple words suggestions. // TODO: Check shortcuts during traversal for multiple words suggestions. const bool sameAsTyped = TRAVERSAL->sameAsTyped(traverseSession, terminalDicNode); diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigrams/bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/bigrams/bigram_list_policy.h new file mode 100644 index 000000000..a9e5da3c7 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/bigrams/bigram_list_policy.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 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. + */ + +#ifndef LATINIME_BIGRAM_LIST_POLICY_H +#define LATINIME_BIGRAM_LIST_POLICY_H + +#include <stdint.h> + +#include "defines.h" +#include "suggest/core/policy/dictionary_bigrams_structure_policy.h" +// TODO: Move bigrams reading methods to policyimpl. +#include "suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h" + +namespace latinime { + +class BigramListPolicy : public DictionaryBigramsStructurePolicy { + public: + explicit BigramListPolicy(const uint8_t *const bigramsBuf) : mBigramsBuf(bigramsBuf) {} + + ~BigramListPolicy() {} + + void getNextBigram(int *const outBigramPos, int *const outProbability, bool *const outHasNext, + int *const pos) const { + const BinaryDictionaryTerminalAttributesReadingUtils::BigramFlags flags = + BinaryDictionaryTerminalAttributesReadingUtils::getFlagsAndForwardPointer( + mBigramsBuf, pos); + *outBigramPos = + BinaryDictionaryTerminalAttributesReadingUtils::getBigramAddressAndForwardPointer( + mBigramsBuf, flags, pos); + *outProbability = + BinaryDictionaryTerminalAttributesReadingUtils::getProbabilityFromFlags(flags); + *outHasNext = BinaryDictionaryTerminalAttributesReadingUtils::hasNext(flags); + } + + void skipAllBigrams(int *const pos) const { + BinaryDictionaryTerminalAttributesReadingUtils::skipExistingBigrams(mBigramsBuf, pos); + } + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(BigramListPolicy); + + const uint8_t *const mBigramsBuf; +}; +} // namespace latinime +#endif // LATINIME_BIGRAM_LIST_POLICY_H diff --git a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_policy_factory.h b/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_policy_factory.h deleted file mode 100644 index c0df89f49..000000000 --- a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_policy_factory.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef LATINIME_DICTIONARY_STRUCTURE_POLICY_FACTORY_H -#define LATINIME_DICTIONARY_STRUCTURE_POLICY_FACTORY_H - -#include "defines.h" -#include "suggest/core/dictionary/binary_dictionary_format_utils.h" -#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h" -#include "suggest/policyimpl/dictionary/patricia_trie_policy.h" - -namespace latinime { - -class DictionaryStructurePolicy; - -class DictionaryStructurePolicyFactory { - public: - static const DictionaryStructurePolicy *getDictionaryStructurePolicy( - const BinaryDictionaryFormatUtils::FORMAT_VERSION dictionaryFormat) { - switch (dictionaryFormat) { - case BinaryDictionaryFormatUtils::VERSION_2: - return PatriciaTriePolicy::getInstance(); - case BinaryDictionaryFormatUtils::VERSION_3: - return DynamicPatriciaTriePolicy::getInstance(); - default: - ASSERT(false); - return 0; - } - } - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructurePolicyFactory); -}; -} // namespace latinime -#endif // LATINIME_DICTIONARY_STRUCTURE_POLICY_FACTORY_H diff --git a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.cpp new file mode 100644 index 000000000..f2c586245 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 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 "suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h" + +#include "defines.h" +#include "suggest/core/dictionary/binary_dictionary_info.h" +#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h" +#include "suggest/policyimpl/dictionary/patricia_trie_policy.h" + +namespace latinime { + +/* static */ DictionaryStructureWithBufferPolicy *DictionaryStructureWithBufferPolicyFactory + ::newDictionaryStructurePolicy( + const BinaryDictionaryInfo *const binaryDictionaryInfo) { + switch (binaryDictionaryInfo->getFormat()) { + case BinaryDictionaryFormatUtils::VERSION_2: + return new PatriciaTriePolicy(binaryDictionaryInfo->getDictRoot(), + binaryDictionaryInfo); + case BinaryDictionaryFormatUtils::VERSION_3: + return new DynamicPatriciaTriePolicy(binaryDictionaryInfo->getDictRoot(), + binaryDictionaryInfo); + default: + ASSERT(false); + return 0; + } +} + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h b/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h new file mode 100644 index 000000000..95f82aabe --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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. + */ + +#ifndef LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H +#define LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H + +#include "defines.h" + +#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h" + +namespace latinime { + +class BinaryDictionaryInfo; + +class DictionaryStructureWithBufferPolicyFactory { + public: + static DictionaryStructureWithBufferPolicy *newDictionaryStructurePolicy( + const BinaryDictionaryInfo *const binaryDictionaryInfo); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory); +}; +} // namespace latinime +#endif // LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp index 7ac635a00..e8799e574 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp @@ -18,6 +18,7 @@ #include "suggest/core/dictionary/binary_dictionary_info.h" #include "suggest/core/dictionary/binary_dictionary_terminal_attributes_reading_utils.h" +#include "suggest/policyimpl/dictionary/bigrams/bigram_list_policy.h" #include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h" namespace latinime { @@ -56,8 +57,7 @@ void DynamicPatriciaTrieNodeReader::fetchNodeInfoFromBufferAndProcessMovedNode(c } if (PatriciaTrieReadingUtils::hasBigrams(mFlags)) { mBigramPos = pos; - BinaryDictionaryTerminalAttributesReadingUtils::skipExistingBigrams( - mBinaryDictionaryInfo, &pos); + mBigramsPolicy->skipAllBigrams(&pos); } else { mBigramPos = NOT_A_DICT_POS; } diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h index 71558edaa..641ac9b5b 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h +++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h @@ -17,13 +17,17 @@ #ifndef LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H #define LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H +#include <stdint.h> + #include "defines.h" +#include "suggest/policyimpl/dictionary/bigrams/bigram_list_policy.h" #include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h" #include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h" namespace latinime { class BinaryDictionaryInfo; +class DictionaryBigramsStructurePolicy; /* * This class is used for helping to read nodes of dynamic patricia trie. This class handles moved @@ -31,10 +35,11 @@ class BinaryDictionaryInfo; */ class DynamicPatriciaTrieNodeReader { public: - explicit DynamicPatriciaTrieNodeReader(const BinaryDictionaryInfo *const binaryDictionaryInfo) - : mBinaryDictionaryInfo(binaryDictionaryInfo), mNodePos(NOT_A_VALID_WORD_POS), - mFlags(0), mParentPos(NOT_A_DICT_POS), mCodePointCount(0), - mProbability(NOT_A_PROBABILITY), mChildrenPos(NOT_A_DICT_POS), + DynamicPatriciaTrieNodeReader(const BinaryDictionaryInfo *const binaryDictionaryInfo, + const DictionaryBigramsStructurePolicy *const bigramsPolicy) + : mBinaryDictionaryInfo(binaryDictionaryInfo), mBigramsPolicy(bigramsPolicy), + mNodePos(NOT_A_VALID_WORD_POS), mFlags(0), mParentPos(NOT_A_DICT_POS), + mCodePointCount(0), mProbability(NOT_A_PROBABILITY), mChildrenPos(NOT_A_DICT_POS), mShortcutPos(NOT_A_DICT_POS), mBigramPos(NOT_A_DICT_POS), mSiblingPos(NOT_A_VALID_WORD_POS) {} @@ -117,6 +122,7 @@ class DynamicPatriciaTrieNodeReader { DISALLOW_COPY_AND_ASSIGN(DynamicPatriciaTrieNodeReader); const BinaryDictionaryInfo *const mBinaryDictionaryInfo; + const DictionaryBigramsStructurePolicy *const mBigramsPolicy; int mNodePos; DynamicPatriciaTrieReadingUtils::NodeFlags mFlags; int mParentPos; diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp index 3df505688..9b384157e 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp @@ -26,23 +26,21 @@ namespace latinime { -const DynamicPatriciaTriePolicy DynamicPatriciaTriePolicy::sInstance; // To avoid infinite loop caused by invalid or malicious forward links. const int DynamicPatriciaTriePolicy::MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP = 100000; void DynamicPatriciaTriePolicy::createAndGetAllChildNodes(const DicNode *const dicNode, - const BinaryDictionaryInfo *const binaryDictionaryInfo, const NodeFilter *const nodeFilter, DicNodeVector *const childDicNodes) const { if (!dicNode->hasChildren()) { return; } - DynamicPatriciaTrieNodeReader nodeReader(binaryDictionaryInfo); + DynamicPatriciaTrieNodeReader nodeReader(mBinaryDictionaryInfo, getBigramsStructurePolicy()); int mergedNodeCodePoints[MAX_WORD_LENGTH]; int nextPos = dicNode->getChildrenPos(); int totalChildCount = 0; do { const int childCount = PatriciaTrieReadingUtils::getGroupCountAndAdvancePosition( - binaryDictionaryInfo->getDictRoot(), &nextPos); + mDictRoot, &nextPos); totalChildCount += childCount; if (childCount <= 0 || totalChildCount > MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP) { // Invalid dictionary. @@ -64,13 +62,11 @@ void DynamicPatriciaTriePolicy::createAndGetAllChildNodes(const DicNode *const d } nextPos = nodeReader.getSiblingNodePos(); } - nextPos = DynamicPatriciaTrieReadingUtils::getForwardLinkPosition( - binaryDictionaryInfo->getDictRoot(), nextPos); + nextPos = DynamicPatriciaTrieReadingUtils::getForwardLinkPosition(mDictRoot, nextPos); } while (DynamicPatriciaTrieReadingUtils::isValidForwardLinkPosition(nextPos)); } int DynamicPatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int nodePos, const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) const { if (nodePos == NOT_A_VALID_WORD_POS) { @@ -83,7 +79,7 @@ int DynamicPatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCoun int mergedNodeCodePoints[maxCodePointCount]; int codePointCount = 0; - DynamicPatriciaTrieNodeReader nodeReader(binaryDictionaryInfo); + DynamicPatriciaTrieNodeReader nodeReader(mBinaryDictionaryInfo, getBigramsStructurePolicy()); // First, read terminal node and get its probability. nodeReader.fetchNodeInfoFromBufferAndGetNodeCodePoints(nodePos, maxCodePointCount, mergedNodeCodePoints); @@ -118,8 +114,7 @@ int DynamicPatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCoun return codePointCount; } -int DynamicPatriciaTriePolicy::getTerminalNodePositionOfWord( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int *const inWord, +int DynamicPatriciaTriePolicy::getTerminalNodePositionOfWord(const int *const inWord, const int length, const bool forceLowerCaseSearch) const { int searchCodePoints[length]; for (int i = 0; i < length; ++i) { @@ -128,14 +123,14 @@ int DynamicPatriciaTriePolicy::getTerminalNodePositionOfWord( int mergedNodeCodePoints[MAX_WORD_LENGTH]; int currentLength = 0; int pos = getRootPosition(); - DynamicPatriciaTrieNodeReader nodeReader(binaryDictionaryInfo); + DynamicPatriciaTrieNodeReader nodeReader(mBinaryDictionaryInfo, getBigramsStructurePolicy()); while (currentLength <= length) { // When foundMatchedNode becomes true, currentLength is increased at least once. bool foundMatchedNode = false; int totalChildCount = 0; do { const int childCount = PatriciaTrieReadingUtils::getGroupCountAndAdvancePosition( - binaryDictionaryInfo->getDictRoot(), &pos); + mDictRoot, &pos); totalChildCount += childCount; if (childCount <= 0 || totalChildCount > MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP) { // Invalid dictionary. @@ -183,7 +178,7 @@ int DynamicPatriciaTriePolicy::getTerminalNodePositionOfWord( // If the matched node is not found in the current node group, try to follow the // forward link. pos = DynamicPatriciaTrieReadingUtils::getForwardLinkPosition( - binaryDictionaryInfo->getDictRoot(), pos); + mDictRoot, pos); } while (DynamicPatriciaTrieReadingUtils::isValidForwardLinkPosition(pos)); if (!foundMatchedNode) { // Matched node is not found. @@ -195,12 +190,11 @@ int DynamicPatriciaTriePolicy::getTerminalNodePositionOfWord( return NOT_A_VALID_WORD_POS; } -int DynamicPatriciaTriePolicy::getUnigramProbability( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int nodePos) const { +int DynamicPatriciaTriePolicy::getUnigramProbability(const int nodePos) const { if (nodePos == NOT_A_VALID_WORD_POS) { return NOT_A_PROBABILITY; } - DynamicPatriciaTrieNodeReader nodeReader(binaryDictionaryInfo); + DynamicPatriciaTrieNodeReader nodeReader(mBinaryDictionaryInfo, getBigramsStructurePolicy()); nodeReader.fetchNodeInfoFromBuffer(nodePos); if (nodeReader.isDeleted() || nodeReader.isBlacklisted() || nodeReader.isNotAWord()) { return NOT_A_PROBABILITY; @@ -208,13 +202,11 @@ int DynamicPatriciaTriePolicy::getUnigramProbability( return nodeReader.getProbability(); } -int DynamicPatriciaTriePolicy::getShortcutPositionOfNode( - const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const { +int DynamicPatriciaTriePolicy::getShortcutPositionOfNode(const int nodePos) const { if (nodePos == NOT_A_VALID_WORD_POS) { return NOT_A_DICT_POS; } - DynamicPatriciaTrieNodeReader nodeReader(binaryDictionaryInfo); + DynamicPatriciaTrieNodeReader nodeReader(mBinaryDictionaryInfo, getBigramsStructurePolicy()); nodeReader.fetchNodeInfoFromBuffer(nodePos); if (nodeReader.isDeleted()) { return NOT_A_DICT_POS; @@ -222,13 +214,11 @@ int DynamicPatriciaTriePolicy::getShortcutPositionOfNode( return nodeReader.getShortcutPos(); } -int DynamicPatriciaTriePolicy::getBigramsPositionOfNode( - const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const { +int DynamicPatriciaTriePolicy::getBigramsPositionOfNode(const int nodePos) const { if (nodePos == NOT_A_VALID_WORD_POS) { return NOT_A_DICT_POS; } - DynamicPatriciaTrieNodeReader nodeReader(binaryDictionaryInfo); + DynamicPatriciaTrieNodeReader nodeReader(mBinaryDictionaryInfo, getBigramsStructurePolicy()); nodeReader.fetchNodeInfoFromBuffer(nodePos); if (nodeReader.isDeleted()) { return NOT_A_DICT_POS; diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h index 6a7977138..2386d937f 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h @@ -17,8 +17,11 @@ #ifndef LATINIME_DYNAMIC_PATRICIA_TRIE_POLICY_H #define LATINIME_DYNAMIC_PATRICIA_TRIE_POLICY_H +#include <stdint.h> + #include "defines.h" -#include "suggest/core/policy/dictionary_structure_policy.h" +#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h" +#include "suggest/policyimpl/dictionary/bigrams/bigram_list_policy.h" namespace latinime { @@ -26,45 +29,47 @@ class BinaryDictionaryInfo; class DicNode; class DicNodeVector; -class DynamicPatriciaTriePolicy : public DictionaryStructurePolicy { +class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { public: - static AK_FORCE_INLINE const DynamicPatriciaTriePolicy *getInstance() { - return &sInstance; - } + DynamicPatriciaTriePolicy(const uint8_t *const dictRoot, + const BinaryDictionaryInfo *const binaryDictionaryInfo) + : mDictRoot(dictRoot), mBinaryDictionaryInfo(binaryDictionaryInfo), + mBigramListPolicy(dictRoot) {} + + ~DynamicPatriciaTriePolicy() {} AK_FORCE_INLINE int getRootPosition() const { return 0; } void createAndGetAllChildNodes(const DicNode *const dicNode, - const BinaryDictionaryInfo *const binaryDictionaryInfo, const NodeFilter *const nodeFilter, DicNodeVector *const childDicNodes) const; int getCodePointsAndProbabilityAndReturnCodePointCount( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int terminalNodePos, const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) const; - int getTerminalNodePositionOfWord( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int *const inWord, + int getTerminalNodePositionOfWord(const int *const inWord, const int length, const bool forceLowerCaseSearch) const; - int getUnigramProbability(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const; + int getUnigramProbability(const int nodePos) const; - int getShortcutPositionOfNode(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const; + int getShortcutPositionOfNode(const int nodePos) const; - int getBigramsPositionOfNode(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const; + int getBigramsPositionOfNode(const int nodePos) const; + + const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const { + return &mBigramListPolicy; + } private: - DISALLOW_COPY_AND_ASSIGN(DynamicPatriciaTriePolicy); - static const DynamicPatriciaTriePolicy sInstance; + DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTriePolicy); static const int MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP; - DynamicPatriciaTriePolicy() {} - ~DynamicPatriciaTriePolicy() {} + const uint8_t *const mDictRoot; + // TODO: remove + const BinaryDictionaryInfo *const mBinaryDictionaryInfo; + const BigramListPolicy mBigramListPolicy; }; } // namespace latinime #endif // LATINIME_DYNAMIC_PATRICIA_TRIE_POLICY_H diff --git a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.cpp index 097f7c86a..7001509ab 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.cpp @@ -27,48 +27,39 @@ namespace latinime { -const PatriciaTriePolicy PatriciaTriePolicy::sInstance; - void PatriciaTriePolicy::createAndGetAllChildNodes(const DicNode *const dicNode, - const BinaryDictionaryInfo *const binaryDictionaryInfo, const NodeFilter *const nodeFilter, DicNodeVector *const childDicNodes) const { if (!dicNode->hasChildren()) { return; } int nextPos = dicNode->getChildrenPos(); const int childCount = PatriciaTrieReadingUtils::getGroupCountAndAdvancePosition( - binaryDictionaryInfo->getDictRoot(), &nextPos); + mDictRoot, &nextPos); for (int i = 0; i < childCount; i++) { - nextPos = createAndGetLeavingChildNode(dicNode, nextPos, binaryDictionaryInfo, - nodeFilter, childDicNodes); + nextPos = createAndGetLeavingChildNode(dicNode, nextPos, nodeFilter, childDicNodes); } } int PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int nodePos, const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) const { - return BinaryFormat::getCodePointsAndProbabilityAndReturnCodePointCount( - binaryDictionaryInfo->getDictRoot(), nodePos, + return BinaryFormat::getCodePointsAndProbabilityAndReturnCodePointCount(mDictRoot, nodePos, maxCodePointCount, outCodePoints, outUnigramProbability); } -int PatriciaTriePolicy::getTerminalNodePositionOfWord( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int *const inWord, +int PatriciaTriePolicy::getTerminalNodePositionOfWord(const int *const inWord, const int length, const bool forceLowerCaseSearch) const { - return BinaryFormat::getTerminalPosition(binaryDictionaryInfo->getDictRoot(), inWord, + return BinaryFormat::getTerminalPosition(mDictRoot, inWord, length, forceLowerCaseSearch); } -int PatriciaTriePolicy::getUnigramProbability( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int nodePos) const { +int PatriciaTriePolicy::getUnigramProbability(const int nodePos) const { if (nodePos == NOT_A_VALID_WORD_POS) { return NOT_A_PROBABILITY; } - const uint8_t *const dictRoot = binaryDictionaryInfo->getDictRoot(); int pos = nodePos; const PatriciaTrieReadingUtils::NodeFlags flags = - PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictRoot, &pos); + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(mDictRoot, &pos); if (!PatriciaTrieReadingUtils::isTerminal(flags)) { return NOT_A_PROBABILITY; } @@ -79,81 +70,73 @@ int PatriciaTriePolicy::getUnigramProbability( // for shortcuts). return NOT_A_PROBABILITY; } - PatriciaTrieReadingUtils::skipCharacters(dictRoot, flags, MAX_WORD_LENGTH, &pos); - return PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(dictRoot, &pos); + PatriciaTrieReadingUtils::skipCharacters(mDictRoot, flags, MAX_WORD_LENGTH, &pos); + return PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mDictRoot, &pos); } -int PatriciaTriePolicy::getShortcutPositionOfNode( - const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const { +int PatriciaTriePolicy::getShortcutPositionOfNode(const int nodePos) const { if (nodePos == NOT_A_VALID_WORD_POS) { return NOT_A_DICT_POS; } - const uint8_t *const dictRoot = binaryDictionaryInfo->getDictRoot(); int pos = nodePos; const PatriciaTrieReadingUtils::NodeFlags flags = - PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictRoot, &pos); + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(mDictRoot, &pos); if (!PatriciaTrieReadingUtils::hasShortcutTargets(flags)) { return NOT_A_DICT_POS; } - PatriciaTrieReadingUtils::skipCharacters(dictRoot, flags, MAX_WORD_LENGTH, &pos); + PatriciaTrieReadingUtils::skipCharacters(mDictRoot, flags, MAX_WORD_LENGTH, &pos); if (PatriciaTrieReadingUtils::isTerminal(flags)) { - PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(dictRoot, &pos); + PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mDictRoot, &pos); } if (PatriciaTrieReadingUtils::hasChildrenInFlags(flags)) { - PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(dictRoot, flags, &pos); + PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(mDictRoot, flags, &pos); } return pos; } -int PatriciaTriePolicy::getBigramsPositionOfNode( - const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const { +int PatriciaTriePolicy::getBigramsPositionOfNode(const int nodePos) const { if (nodePos == NOT_A_VALID_WORD_POS) { return NOT_A_DICT_POS; } - const uint8_t *const dictRoot = binaryDictionaryInfo->getDictRoot(); int pos = nodePos; const PatriciaTrieReadingUtils::NodeFlags flags = - PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictRoot, &pos); + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(mDictRoot, &pos); if (!PatriciaTrieReadingUtils::hasBigrams(flags)) { return NOT_A_DICT_POS; } - PatriciaTrieReadingUtils::skipCharacters(dictRoot, flags, MAX_WORD_LENGTH, &pos); + PatriciaTrieReadingUtils::skipCharacters(mDictRoot, flags, MAX_WORD_LENGTH, &pos); if (PatriciaTrieReadingUtils::isTerminal(flags)) { - PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(dictRoot, &pos); + PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mDictRoot, &pos); } if (PatriciaTrieReadingUtils::hasChildrenInFlags(flags)) { - PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(dictRoot, flags, &pos); + PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(mDictRoot, flags, &pos); } if (PatriciaTrieReadingUtils::hasShortcutTargets(flags)) { - BinaryDictionaryTerminalAttributesReadingUtils::skipShortcuts(binaryDictionaryInfo, &pos); + BinaryDictionaryTerminalAttributesReadingUtils::skipShortcuts(mBinaryDictionaryInfo, &pos); } return pos; } int PatriciaTriePolicy::createAndGetLeavingChildNode(const DicNode *const dicNode, - const int nodePos, const BinaryDictionaryInfo *const binaryDictionaryInfo, - const NodeFilter *const childrenFilter, DicNodeVector *childDicNodes) const { - const uint8_t *const dictRoot = binaryDictionaryInfo->getDictRoot(); + const int nodePos, const NodeFilter *const childrenFilter, + DicNodeVector *childDicNodes) const { int pos = nodePos; const PatriciaTrieReadingUtils::NodeFlags flags = - PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictRoot, &pos); + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(mDictRoot, &pos); int mergedNodeCodePoints[MAX_WORD_LENGTH]; const int mergedNodeCodePointCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition( - dictRoot, flags, MAX_WORD_LENGTH, mergedNodeCodePoints, &pos); + mDictRoot, flags, MAX_WORD_LENGTH, mergedNodeCodePoints, &pos); const int probability = (PatriciaTrieReadingUtils::isTerminal(flags))? - PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(dictRoot, &pos) + PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mDictRoot, &pos) : NOT_A_PROBABILITY; const int childrenPos = PatriciaTrieReadingUtils::hasChildrenInFlags(flags) ? PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition( - dictRoot, flags, &pos) : NOT_A_DICT_POS; + mDictRoot, flags, &pos) : NOT_A_DICT_POS; if (PatriciaTrieReadingUtils::hasShortcutTargets(flags)) { - BinaryDictionaryTerminalAttributesReadingUtils::skipShortcuts(binaryDictionaryInfo, &pos); + BinaryDictionaryTerminalAttributesReadingUtils::skipShortcuts(mBinaryDictionaryInfo, &pos); } if (PatriciaTrieReadingUtils::hasBigrams(flags)) { - BinaryDictionaryTerminalAttributesReadingUtils::skipExistingBigrams( - binaryDictionaryInfo, &pos); + getBigramsStructurePolicy()->skipAllBigrams(&pos); } if (!childrenFilter->isFilteredOut(mergedNodeCodePoints[0])) { childDicNodes->pushLeavingChild(dicNode, nodePos, childrenPos, probability, diff --git a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h index 71f256eee..bebee39fb 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h @@ -17,52 +17,60 @@ #ifndef LATINIME_PATRICIA_TRIE_POLICY_H #define LATINIME_PATRICIA_TRIE_POLICY_H +#include <stdint.h> + #include "defines.h" -#include "suggest/core/policy/dictionary_structure_policy.h" +#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h" +#include "suggest/policyimpl/dictionary/bigrams/bigram_list_policy.h" namespace latinime { -class PatriciaTriePolicy : public DictionaryStructurePolicy { +class BinaryDictionaryInfo; +class DicNode; +class DicNodeVector; + +class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { public: - static AK_FORCE_INLINE const PatriciaTriePolicy *getInstance() { - return &sInstance; - } + PatriciaTriePolicy(const uint8_t *const dictRoot, + const BinaryDictionaryInfo *const binaryDictionaryInfo) + : mDictRoot(dictRoot), mBinaryDictionaryInfo(binaryDictionaryInfo), + mBigramListPolicy(dictRoot) {} + + ~PatriciaTriePolicy() {} AK_FORCE_INLINE int getRootPosition() const { return 0; } void createAndGetAllChildNodes(const DicNode *const dicNode, - const BinaryDictionaryInfo *const binaryDictionaryInfo, const NodeFilter *const nodeFilter, DicNodeVector *const childDicNodes) const; int getCodePointsAndProbabilityAndReturnCodePointCount( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int terminalNodePos, const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) const; - int getTerminalNodePositionOfWord( - const BinaryDictionaryInfo *const binaryDictionaryInfo, const int *const inWord, + int getTerminalNodePositionOfWord(const int *const inWord, const int length, const bool forceLowerCaseSearch) const; - int getUnigramProbability(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const; + int getUnigramProbability(const int nodePos) const; + + int getShortcutPositionOfNode(const int nodePos) const; - int getShortcutPositionOfNode(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const; + int getBigramsPositionOfNode(const int nodePos) const; - int getBigramsPositionOfNode(const BinaryDictionaryInfo *const binaryDictionaryInfo, - const int nodePos) const; + const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const { + return &mBigramListPolicy; + } private: - DISALLOW_COPY_AND_ASSIGN(PatriciaTriePolicy); - static const PatriciaTriePolicy sInstance; + DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy); - PatriciaTriePolicy() {} - ~PatriciaTriePolicy() {} + const uint8_t *const mDictRoot; + // TODO: remove + const BinaryDictionaryInfo *const mBinaryDictionaryInfo; + const BigramListPolicy mBigramListPolicy; int createAndGetLeavingChildNode(const DicNode *const dicNode, const int nodePos, - const BinaryDictionaryInfo *const binaryDictionaryInfo, const NodeFilter *const nodeFilter, DicNodeVector *const childDicNodes) const; }; } // namespace latinime |