aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java6
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java5
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java6
-rw-r--r--native/src/binary_format.h4
-rw-r--r--native/src/dictionary.h75
-rw-r--r--native/src/unigram_dictionary.cpp7
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java109
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java148
-rw-r--r--tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java50
-rw-r--r--tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java10
11 files changed, 229 insertions, 197 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 2add2921b..54d842f09 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -324,6 +324,12 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
setKeyboard(mKeyboardSet.getSymbolsShiftedKeyboard());
}
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void requestUpdatingShiftState() {
+ mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
+ }
+
public boolean isInMomentarySwitchState() {
return mState.isInMomentarySwitchState();
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index f54bdbb05..42f069c83 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -53,6 +53,11 @@ public class KeyboardState {
public void setSymbolsKeyboard();
public void setSymbolsShiftedKeyboard();
+
+ /**
+ * Request to call back {@link KeyboardState#onUpdateShiftState(boolean)}.
+ */
+ public void requestUpdatingShiftState();
}
private KeyboardShiftState mKeyboardShiftState = new KeyboardShiftState();
@@ -212,6 +217,7 @@ public class KeyboardState {
mSwitchState = SWITCH_STATE_ALPHA;
setShiftLocked(mPrevMainKeyboardWasShiftLocked);
mPrevMainKeyboardWasShiftLocked = false;
+ mSwitchActions.requestUpdatingShiftState();
}
private void setSymbolsKeyboard() {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 59de798d8..e60f55060 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1019,7 +1019,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public boolean onEvaluateFullscreenMode() {
- return super.onEvaluateFullscreenMode() && mSettingsValues.mUseFullScreenMode;
+ // Reread resource value here, because this method is called by framework anytime as needed.
+ final boolean isFullscreenModeAllowed =
+ mSettingsValues.isFullscreenModeAllowed(getResources());
+ return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed;
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 83b27f7fe..0ae28d3fc 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -41,7 +41,6 @@ public class SettingsValues {
private final String mSymbolsExcludedFromWordSeparators;
public final String mWordSeparators;
public final CharSequence mHintToSaveText;
- public final boolean mUseFullScreenMode;
// From preferences, in the same order as xml/prefs.xml:
public final boolean mAutoCap;
@@ -107,7 +106,6 @@ public class SettingsValues {
mWordSeparators = createWordSeparators(mMagicSpaceStrippers, mMagicSpaceSwappers,
mSymbolsExcludedFromWordSeparators, res);
mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
- mUseFullScreenMode = res.getBoolean(R.bool.config_use_fullscreen_mode);
// Get the settings preferences
mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
@@ -294,6 +292,10 @@ public class SettingsValues {
return mVoiceKeyOnMain;
}
+ public boolean isFullscreenModeAllowed(Resources res) {
+ return res.getBoolean(R.bool.config_use_fullscreen_mode);
+ }
+
// Accessed from the settings interface, hence public
public static float getCurrentKeypressSoundVolume(final SharedPreferences sp,
final Resources res) {
diff --git a/native/src/binary_format.h b/native/src/binary_format.h
index 9944fa2bd..1d74998f6 100644
--- a/native/src/binary_format.h
+++ b/native/src/binary_format.h
@@ -61,7 +61,9 @@ inline int BinaryFormat::detectFormat(const uint8_t* const dict) {
}
inline int BinaryFormat::getGroupCountAndForwardPointer(const uint8_t* const dict, int* pos) {
- return dict[(*pos)++];
+ const int msb = dict[(*pos)++];
+ if (msb < 0x80) return msb;
+ return ((msb & 0x7F) << 8) | dict[(*pos)++];
}
inline uint8_t BinaryFormat::getFlagsAndForwardPointer(const uint8_t* const dict, int* pos) {
diff --git a/native/src/dictionary.h b/native/src/dictionary.h
index 79d377a4f..90d7148d5 100644
--- a/native/src/dictionary.h
+++ b/native/src/dictionary.h
@@ -56,16 +56,7 @@ class Dictionary {
// public static utility methods
// static inline methods should be defined in the header file
- static unsigned short getChar(const unsigned char *dict, int *pos);
- static int getCount(const unsigned char *dict, int *pos);
- static bool getTerminal(const unsigned char *dict, int *pos);
- static int getAddress(const unsigned char *dict, int *pos);
- static int getFreq(const unsigned char *dict, const bool isLatestDictVersion, int *pos);
static int wideStrLen(unsigned short *str);
- // returns next sibling's position
- static int setDictionaryValues(const unsigned char *dict, const bool isLatestDictVersion,
- const int pos, unsigned short *c, int *childrenPosition,
- bool *terminal, int *freq);
private:
bool hasBigram();
@@ -87,56 +78,6 @@ class Dictionary {
// public static utility methods
// static inline methods should be defined in the header file
-inline unsigned short Dictionary::getChar(const unsigned char *dict, int *pos) {
- unsigned short ch = (unsigned short) (dict[(*pos)++] & 0xFF);
- // If the code is 255, then actual 16 bit code follows (in big endian)
- if (ch == 0xFF) {
- ch = ((dict[*pos] & 0xFF) << 8) | (dict[*pos + 1] & 0xFF);
- (*pos) += 2;
- }
- return ch;
-}
-
-inline int Dictionary::getCount(const unsigned char *dict, int *pos) {
- return dict[(*pos)++] & 0xFF;
-}
-
-inline bool Dictionary::getTerminal(const unsigned char *dict, int *pos) {
- return (dict[*pos] & FLAG_TERMINAL_MASK) > 0;
-}
-
-inline int Dictionary::getAddress(const unsigned char *dict, int *pos) {
- int address = 0;
- if ((dict[*pos] & FLAG_ADDRESS_MASK) == 0) {
- *pos += 1;
- } else {
- address += (dict[*pos] & (ADDRESS_MASK >> 16)) << 16;
- address += (dict[*pos + 1] & 0xFF) << 8;
- address += (dict[*pos + 2] & 0xFF);
- *pos += 3;
- }
- return address;
-}
-
-inline int Dictionary::getFreq(const unsigned char *dict,
- const bool isLatestDictVersion, int *pos) {
- int freq = dict[(*pos)++] & 0xFF;
- if (isLatestDictVersion) {
- // skipping bigram
- int bigramExist = (dict[*pos] & FLAG_BIGRAM_READ);
- if (bigramExist > 0) {
- int nextBigramExist = 1;
- while (nextBigramExist > 0) {
- (*pos) += 3;
- nextBigramExist = (dict[(*pos)++] & FLAG_BIGRAM_CONTINUED);
- }
- } else {
- (*pos)++;
- }
- }
- return freq;
-}
-
inline int Dictionary::wideStrLen(unsigned short *str) {
if (!str) return 0;
unsigned short *end = str;
@@ -144,22 +85,6 @@ inline int Dictionary::wideStrLen(unsigned short *str) {
end++;
return end - str;
}
-
-inline int Dictionary::setDictionaryValues(const unsigned char *dict,
- const bool isLatestDictVersion, const int pos, unsigned short *c,int *childrenPosition,
- bool *terminal, int *freq) {
- int position = pos;
- // -- at char
- *c = Dictionary::getChar(dict, &position);
- // -- at flag/add
- *terminal = Dictionary::getTerminal(dict, &position);
- *childrenPosition = Dictionary::getAddress(dict, &position);
- // -- after address or flag
- *freq = (*terminal) ? Dictionary::getFreq(dict, isLatestDictVersion, &position) : 1;
- // returns next sibling's position
- return position;
-}
-
} // namespace latinime
#endif // LATINIME_DICTIONARY_H
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index 1cff4d838..85e7e9bf2 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -277,7 +277,7 @@ void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance,
doAutoCompletion, maxErrors);
int rootPosition = ROOT_POS;
// Get the number of children of root, then increment the position
- int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition);
+ int childCount = BinaryFormat::getGroupCountAndForwardPointer(DICT_ROOT, &rootPosition);
int outputIndex = 0;
correction->initCorrectionState(rootPosition, childCount, (inputLength <= 0));
@@ -523,9 +523,10 @@ int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWor
int maxFreq = -1;
const uint8_t* const root = DICT_ROOT;
- mStackChildCount[0] = root[0];
+ int startPos = 0;
+ mStackChildCount[0] = BinaryFormat::getGroupCountAndForwardPointer(root, &startPos);
mStackInputIndex[0] = 0;
- mStackSiblingPos[0] = 1;
+ mStackSiblingPos[0] = startPos;
while (depth >= 0) {
const int charGroupCount = mStackChildCount[depth];
int pos = mStackSiblingPos[depth];
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java
index 9dc1fac3e..a47e2e5a1 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java
@@ -19,101 +19,8 @@ package com.android.inputmethod.keyboard.internal;
import android.test.AndroidTestCase;
import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.internal.KeyboardState.SwitchActions;
public class KeyboardStateTests extends AndroidTestCase {
- private static final int ALPHABET_UNSHIFTED = 0;
- private static final int ALPHABET_MANUAL_SHIFTED = 1;
- private static final int ALPHABET_AUTOMATIC_SHIFTED = 2;
- private static final int ALPHABET_SHIFT_LOCKED = 3;
- private static final int SYMBOLS_UNSHIFTED = 4;
- private static final int SYMBOLS_SHIFTED = 5;
-
- static class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
- public int mLayout = ALPHABET_UNSHIFTED;
-
- public boolean mAutoCaps = NO_AUTO_CAPS;
-
- final KeyboardState mState = new KeyboardState(this);
-
- @Override
- public void setAlphabetKeyboard() {
- mLayout = ALPHABET_UNSHIFTED;
- }
-
- @Override
- public void setShifted(int shiftMode) {
- if (shiftMode == SwitchActions.UNSHIFT) {
- mLayout = ALPHABET_UNSHIFTED;
- } else if (shiftMode == SwitchActions.MANUAL_SHIFT) {
- mLayout = ALPHABET_MANUAL_SHIFTED;
- } else if (shiftMode == SwitchActions.AUTOMATIC_SHIFT) {
- mLayout = ALPHABET_AUTOMATIC_SHIFTED;
- }
- }
-
- @Override
- public void setShiftLocked(boolean shiftLocked) {
- if (shiftLocked) {
- mLayout = ALPHABET_SHIFT_LOCKED;
- } else {
- mLayout = ALPHABET_UNSHIFTED;
- }
- }
-
- @Override
- public void setSymbolsKeyboard() {
- mLayout = SYMBOLS_UNSHIFTED;
- }
-
- @Override
- public void setSymbolsShiftedKeyboard() {
- mLayout = SYMBOLS_SHIFTED;
- }
-
- public void toggleCapsLock() {
- mState.onToggleCapsLock();
- }
-
- public void updateShiftState() {
- mState.onUpdateShiftState(mAutoCaps);
- }
-
- public void loadKeyboard(String layoutSwitchBackSymbols,
- boolean hasDistinctMultitouch) {
- mState.onLoadKeyboard(layoutSwitchBackSymbols, hasDistinctMultitouch);
- }
-
- public void onPressShift(boolean withSliding) {
- mState.onPressShift(withSliding);
- }
-
- public void onReleaseShift(boolean withSliding) {
- mState.onReleaseShift(withSliding);
- }
-
- public void onPressSymbol() {
- mState.onPressSymbol();
- }
-
- public void onReleaseSymbol() {
- mState.onReleaseSymbol();
- }
-
- public void onOtherKeyPressed() {
- mState.onOtherKeyPressed();
- }
-
- public void onCodeInput(int code, boolean isSinglePointer) {
- mState.onCodeInput(code, isSinglePointer, mAutoCaps);
- }
-
- public void onCancelInput(boolean isSinglePointer) {
- mState.onCancelInput(isSinglePointer);
- }
-
- }
-
private MockKeyboardSwitcher mSwitcher;
@Override
@@ -134,31 +41,31 @@ public class KeyboardStateTests extends AndroidTestCase {
// Argument for KeyboardState.onCodeInput.
private static final boolean SINGLE = true;
private static final boolean MULTI = false;
- private static final boolean NO_AUTO_CAPS = false;
+ static final boolean NO_AUTO_CAPS = false;
private static final boolean AUTO_CAPS = true;
private void assertAlphabetNormal() {
- assertEquals(ALPHABET_UNSHIFTED, mSwitcher.mLayout);
+ assertTrue(mSwitcher.assertAlphabetNormal());
}
private void assertAlphabetManualShifted() {
- assertEquals(ALPHABET_MANUAL_SHIFTED, mSwitcher.mLayout);
+ assertTrue(mSwitcher.assertAlphabetManualShifted());
}
private void assertAlphabetAutomaticShifted() {
- assertEquals(ALPHABET_AUTOMATIC_SHIFTED, mSwitcher.mLayout);
+ assertTrue(mSwitcher.assertAlphabetAutomaticShifted());
}
private void assertAlphabetShiftLocked() {
- assertEquals(ALPHABET_SHIFT_LOCKED, mSwitcher.mLayout);
+ assertTrue(mSwitcher.assertAlphabetShiftLocked());
}
private void assertSymbolsNormal() {
- assertEquals(SYMBOLS_UNSHIFTED, mSwitcher.mLayout);
+ assertTrue(mSwitcher.assertSymbolsNormal());
}
private void assertSymbolsShifted() {
- assertEquals(SYMBOLS_SHIFTED, mSwitcher.mLayout);
+ assertTrue(mSwitcher.assertSymbolsShifted());
}
// Initial state test.
@@ -227,7 +134,7 @@ public class KeyboardStateTests extends AndroidTestCase {
// Automatic upper case test
public void testAutomaticUpperCase() {
- mSwitcher.mAutoCaps = AUTO_CAPS;
+ mSwitcher.setAutoCapsMode(AUTO_CAPS);
// Update shift state with auto caps enabled.
mSwitcher.updateShiftState();
assertAlphabetAutomaticShifted();
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
new file mode 100644
index 000000000..d5c647cd2
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import com.android.inputmethod.keyboard.internal.KeyboardState.SwitchActions;
+
+public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
+ public static final String WORD_SEPARATORS = " ,.";
+
+ private static final int ALPHABET_UNSHIFTED = 0;
+ private static final int ALPHABET_MANUAL_SHIFTED = 1;
+ private static final int ALPHABET_AUTOMATIC_SHIFTED = 2;
+ private static final int ALPHABET_SHIFT_LOCKED = 3;
+ private static final int SYMBOLS_UNSHIFTED = 4;
+ private static final int SYMBOLS_SHIFTED = 5;
+
+ private int mLayout = ALPHABET_UNSHIFTED;
+
+ private boolean mAutoCapsMode = KeyboardStateTests.NO_AUTO_CAPS;
+ // Following InputConnection's behavior. Simulating InputType.TYPE_TEXT_FLAG_CAP_WORDS.
+ private boolean mAutoCapsState = true;
+
+ private final KeyboardState mState = new KeyboardState(this);
+
+ public boolean assertAlphabetNormal() {
+ return mLayout == ALPHABET_UNSHIFTED;
+ }
+
+ public boolean assertAlphabetManualShifted() {
+ return mLayout == ALPHABET_MANUAL_SHIFTED;
+ }
+
+ public boolean assertAlphabetAutomaticShifted() {
+ return mLayout == ALPHABET_AUTOMATIC_SHIFTED;
+ }
+
+ public boolean assertAlphabetShiftLocked() {
+ return mLayout == ALPHABET_SHIFT_LOCKED;
+ }
+
+ public boolean assertSymbolsNormal() {
+ return mLayout == SYMBOLS_UNSHIFTED;
+ }
+
+ public boolean assertSymbolsShifted() {
+ return mLayout == SYMBOLS_SHIFTED;
+ }
+
+ public void setAutoCapsMode(boolean autoCaps) {
+ mAutoCapsMode = autoCaps;
+ }
+
+ @Override
+ public void setAlphabetKeyboard() {
+ mLayout = ALPHABET_UNSHIFTED;
+ }
+
+ @Override
+ public void setShifted(int shiftMode) {
+ if (shiftMode == SwitchActions.UNSHIFT) {
+ mLayout = ALPHABET_UNSHIFTED;
+ } else if (shiftMode == SwitchActions.MANUAL_SHIFT) {
+ mLayout = ALPHABET_MANUAL_SHIFTED;
+ } else if (shiftMode == SwitchActions.AUTOMATIC_SHIFT) {
+ mLayout = ALPHABET_AUTOMATIC_SHIFTED;
+ }
+ }
+
+ @Override
+ public void setShiftLocked(boolean shiftLocked) {
+ if (shiftLocked) {
+ mLayout = ALPHABET_SHIFT_LOCKED;
+ } else {
+ mLayout = ALPHABET_UNSHIFTED;
+ }
+ }
+
+ @Override
+ public void setSymbolsKeyboard() {
+ mLayout = SYMBOLS_UNSHIFTED;
+ }
+
+ @Override
+ public void setSymbolsShiftedKeyboard() {
+ mLayout = SYMBOLS_SHIFTED;
+ }
+
+ @Override
+ public void requestUpdatingShiftState() {
+ mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState);
+ }
+
+ public void toggleCapsLock() {
+ mState.onToggleCapsLock();
+ }
+
+ public void updateShiftState() {
+ mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState);
+ }
+
+ public void loadKeyboard(String layoutSwitchBackSymbols,
+ boolean hasDistinctMultitouch) {
+ mState.onLoadKeyboard(layoutSwitchBackSymbols, hasDistinctMultitouch);
+ }
+
+ public void onPressShift(boolean withSliding) {
+ mState.onPressShift(withSliding);
+ }
+
+ public void onReleaseShift(boolean withSliding) {
+ mState.onReleaseShift(withSliding);
+ }
+
+ public void onPressSymbol() {
+ mState.onPressSymbol();
+ }
+
+ public void onReleaseSymbol() {
+ mState.onReleaseSymbol();
+ }
+
+ public void onOtherKeyPressed() {
+ mState.onOtherKeyPressed();
+ }
+
+ public void onCodeInput(int code, boolean isSinglePointer) {
+ mAutoCapsState = (WORD_SEPARATORS.indexOf(code) >= 0);
+ mState.onCodeInput(code, isSinglePointer, mAutoCapsMode && mAutoCapsState);
+ }
+
+ public void onCancelInput(boolean isSinglePointer) {
+ mState.onCancelInput(isSinglePointer);
+ }
+} \ No newline at end of file
diff --git a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java
index fcbb645f5..ae54c5d77 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java
@@ -144,7 +144,6 @@ public class BinaryDictInputOutput {
private static final int GROUP_CHARACTERS_TERMINATOR = 0x1F;
- private static final int GROUP_COUNT_SIZE = 1;
private static final int GROUP_TERMINATOR_SIZE = 1;
private static final int GROUP_FLAGS_SIZE = 1;
private static final int GROUP_FREQUENCY_SIZE = 1;
@@ -155,9 +154,8 @@ public class BinaryDictInputOutput {
private static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE;
private static final int INVALID_CHARACTER = -1;
- // Limiting to 127 for upward compatibility
- // TODO: implement a scheme to be able to shoot 256 chargroups in a node
- private static final int MAX_CHARGROUPS_IN_A_NODE = 127;
+ private static final int MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT = 0x7F; // 127
+ private static final int MAX_CHARGROUPS_IN_A_NODE = 0x7FFF; // 32767
private static final int MAX_TERMINAL_FREQUENCY = 255;
@@ -267,6 +265,22 @@ public class BinaryDictInputOutput {
}
/**
+ * Compute the binary size of the group count for a node
+ * @param node the node
+ * @return the size of the group count, either 1 or 2 bytes.
+ */
+ private static int getGroupCountSize(final Node node) {
+ if (MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT >= node.mData.size()) {
+ return 1;
+ } else if (MAX_CHARGROUPS_IN_A_NODE >= node.mData.size()) {
+ return 2;
+ } else {
+ throw new RuntimeException("Can't have more than " + MAX_CHARGROUPS_IN_A_NODE
+ + " groups in a node (found " + node.mData.size() +")");
+ }
+ }
+
+ /**
* Compute the maximum size of a CharGroup, assuming 3-byte addresses for everything.
*
* @param group the CharGroup to compute the size of.
@@ -295,7 +309,7 @@ public class BinaryDictInputOutput {
* @param node the node to compute the maximum size of.
*/
private static void setNodeMaximumSize(Node node) {
- int size = GROUP_COUNT_SIZE;
+ int size = getGroupCountSize(node);
for (CharGroup g : node.mData) {
final int groupSize = getCharGroupMaximumSize(g);
g.mCachedSize = groupSize;
@@ -394,7 +408,7 @@ public class BinaryDictInputOutput {
* @param dict the dictionary in which the word/attributes are to be found.
*/
private static void computeActualNodeSize(Node node, FusionDictionary dict) {
- int size = GROUP_COUNT_SIZE;
+ int size = getGroupCountSize(node);
for (CharGroup group : node.mData) {
int groupSize = GROUP_FLAGS_SIZE + getGroupCharactersSize(group);
if (group.isTerminal()) groupSize += GROUP_FREQUENCY_SIZE;
@@ -437,12 +451,13 @@ public class BinaryDictInputOutput {
int nodeOffset = 0;
for (Node n : flatNodes) {
n.mCachedAddress = nodeOffset;
+ int groupCountSize = getGroupCountSize(n);
int groupOffset = 0;
for (CharGroup g : n.mData) {
- g.mCachedAddress = GROUP_COUNT_SIZE + nodeOffset + groupOffset;
+ g.mCachedAddress = groupCountSize + nodeOffset + groupOffset;
groupOffset += g.mCachedSize;
}
- if (groupOffset + GROUP_COUNT_SIZE != n.mCachedSize) {
+ if (groupOffset + groupCountSize != n.mCachedSize) {
throw new RuntimeException("Bug : Stored and computed node size differ");
}
nodeOffset += n.mCachedSize;
@@ -629,13 +644,20 @@ public class BinaryDictInputOutput {
private static int writePlacedNode(FusionDictionary dict, byte[] buffer, Node node) {
int index = node.mCachedAddress;
- final int size = node.mData.size();
- if (size > MAX_CHARGROUPS_IN_A_NODE)
- throw new RuntimeException("A node has a group count over 127 (" + size + ").");
-
- buffer[index++] = (byte)size;
+ final int groupCount = node.mData.size();
+ final int countSize = getGroupCountSize(node);
+ if (1 == countSize) {
+ buffer[index++] = (byte)groupCount;
+ } else if (2 == countSize) {
+ // We need to signal 2-byte size by setting the top bit of the MSB to 1, so
+ // we | 0x80 to do this.
+ buffer[index++] = (byte)((groupCount >> 8) | 0x80);
+ buffer[index++] = (byte)(groupCount & 0xFF);
+ } else {
+ throw new RuntimeException("Strange size from getGroupCountSize : " + countSize);
+ }
int groupAddress = index;
- for (int i = 0; i < size; ++i) {
+ for (int i = 0; i < groupCount; ++i) {
CharGroup group = node.mData.get(i);
if (index != group.mCachedAddress) throw new RuntimeException("Bug: write index is not "
+ "the same as the cached address of the group");
diff --git a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
index 2327e1972..3ab206d80 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
@@ -435,6 +435,16 @@ public class FusionDictionary implements Iterable<Word> {
}
/**
+ * Helper method to find out whether a word is in the dict or not.
+ */
+ public boolean hasWord(final String s) {
+ if (null == s || "".equals(s)) {
+ throw new RuntimeException("Can't search for a null or empty string");
+ }
+ return null != findWordInTree(mRoot, s);
+ }
+
+ /**
* Recursively count the number of character groups in a given branch of the trie.
*
* @param node the parent node.