diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java index ceb8fa81f..5b319ad90 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java @@ -342,13 +342,11 @@ public final class BinaryDictDecoderUtils { * @param formatOptions file format options. * @return the word with its frequency, as a weighted string. */ - /* package for tests */ static WeightedString getWordAtPosition( - final Ver3DictDecoder dictDecoder, final int headerSize, final int pos, - final FormatOptions formatOptions) { - final DictBuffer dictBuffer = dictDecoder.getDictBuffer(); + /* package for tests */ static WeightedString getWordAtPosition(final DictDecoder dictDecoder, + final int headerSize, final int pos, final FormatOptions formatOptions) { final WeightedString result; - final int originalPos = dictBuffer.position(); - dictBuffer.position(pos); + final int originalPos = dictDecoder.getPosition(); + dictDecoder.setPosition(pos); if (BinaryDictIOUtils.supportsDynamicUpdate(formatOptions)) { result = getWordAtPositionWithParentAddress(dictDecoder, pos, formatOptions); @@ -357,14 +355,13 @@ public final class BinaryDictDecoderUtils { formatOptions); } - dictBuffer.position(originalPos); + dictDecoder.setPosition(originalPos); return result; } @SuppressWarnings("unused") - private static WeightedString getWordAtPositionWithParentAddress( - final Ver3DictDecoder dictDecoder, final int pos, final FormatOptions options) { - final DictBuffer dictBuffer = dictDecoder.getDictBuffer(); + private static WeightedString getWordAtPositionWithParentAddress(final DictDecoder dictDecoder, + final int pos, final FormatOptions options) { int currentPos = pos; int frequency = Integer.MIN_VALUE; final StringBuilder builder = new StringBuilder(); @@ -373,7 +370,7 @@ public final class BinaryDictDecoderUtils { PtNodeInfo currentInfo; int loopCounter = 0; do { - dictBuffer.position(currentPos); + dictDecoder.setPosition(currentPos); currentInfo = dictDecoder.readPtNode(currentPos, options); if (BinaryDictIOUtils.isMovedPtNode(currentInfo.mFlags, options)) { currentPos = currentInfo.mParentAddress + currentInfo.mOriginalAddress; @@ -392,11 +389,10 @@ public final class BinaryDictDecoderUtils { } private static WeightedString getWordAtPositionWithoutParentAddress( - final Ver3DictDecoder dictDecoder, final int headerSize, final int pos, + final DictDecoder dictDecoder, final int headerSize, final int pos, final FormatOptions options) { - final DictBuffer dictBuffer = dictDecoder.getDictBuffer(); - dictBuffer.position(headerSize); - final int count = readPtNodeCount(dictBuffer); + dictDecoder.setPosition(headerSize); + final int count = dictDecoder.readPtNodeCount(); int groupPos = headerSize + BinaryDictIOUtils.getPtNodeCountSize(count); final StringBuilder builder = new StringBuilder(); WeightedString result = null; @@ -414,8 +410,8 @@ public final class BinaryDictDecoderUtils { if (info.mChildrenAddress > pos) { if (null == last) continue; builder.append(new String(last.mCharacters, 0, last.mCharacters.length)); - dictBuffer.position(last.mChildrenAddress); - i = readPtNodeCount(dictBuffer); + dictDecoder.setPosition(last.mChildrenAddress); + i = dictDecoder.readPtNodeCount(); groupPos = last.mChildrenAddress + BinaryDictIOUtils.getPtNodeCountSize(i); last = null; continue; @@ -424,8 +420,8 @@ public final class BinaryDictDecoderUtils { } if (0 == i && BinaryDictIOUtils.hasChildrenAddress(last.mChildrenAddress)) { builder.append(new String(last.mCharacters, 0, last.mCharacters.length)); - dictBuffer.position(last.mChildrenAddress); - i = readPtNodeCount(dictBuffer); + dictDecoder.setPosition(last.mChildrenAddress); + i = dictDecoder.readPtNodeCount(); groupPos = last.mChildrenAddress + BinaryDictIOUtils.getPtNodeCountSize(i); last = null; continue; @@ -449,17 +445,16 @@ public final class BinaryDictDecoderUtils { * @param options file format options. * @return the read node array with all his children already read. */ - private static PtNodeArray readNodeArray(final Ver3DictDecoder dictDecoder, + private static PtNodeArray readNodeArray(final DictDecoder dictDecoder, final int headerSize, final Map reverseNodeArrayMap, final Map reversePtNodeMap, final FormatOptions options) throws IOException { - final DictBuffer dictBuffer = dictDecoder.getDictBuffer(); final ArrayList nodeArrayContents = new ArrayList(); - final int nodeArrayOriginPos = dictBuffer.position(); + final int nodeArrayOriginPos = dictDecoder.getPosition(); do { // Scan the linked-list node. - final int nodeArrayHeadPos = dictBuffer.position(); - final int count = readPtNodeCount(dictBuffer); + final int nodeArrayHeadPos = dictDecoder.getPosition(); + final int count = dictDecoder.readPtNodeCount(); int groupOffsetPos = nodeArrayHeadPos + BinaryDictIOUtils.getPtNodeCountSize(count); for (int i = count; i > 0; --i) { // Scan the array of PtNode. PtNodeInfo info = dictDecoder.readPtNode(groupOffsetPos, options); @@ -480,11 +475,11 @@ public final class BinaryDictDecoderUtils { if (BinaryDictIOUtils.hasChildrenAddress(info.mChildrenAddress)) { PtNodeArray children = reverseNodeArrayMap.get(info.mChildrenAddress); if (null == children) { - final int currentPosition = dictBuffer.position(); - dictBuffer.position(info.mChildrenAddress); + final int currentPosition = dictDecoder.getPosition(); + dictDecoder.setPosition(info.mChildrenAddress); children = readNodeArray(dictDecoder, headerSize, reverseNodeArrayMap, reversePtNodeMap, options); - dictBuffer.position(currentPosition); + dictDecoder.setPosition(currentPosition); } nodeArrayContents.add( new PtNode(info.mCharacters, shortcutTargets, bigrams, @@ -503,15 +498,10 @@ public final class BinaryDictDecoderUtils { // reach the end of the array. if (options.mSupportsDynamicUpdate) { - final int nextAddress = dictBuffer.readUnsignedInt24(); - if (nextAddress >= 0 && nextAddress < dictBuffer.limit()) { - dictBuffer.position(nextAddress); - } else { - break; - } + final boolean hasValidForwardLink = dictDecoder.readForwardLinkAndAdvancePosition(); + if (!hasValidForwardLink) break; } - } while (options.mSupportsDynamicUpdate && - dictBuffer.position() != FormatSpec.NO_FORWARD_LINK_ADDRESS); + } while (options.mSupportsDynamicUpdate && dictDecoder.hasNextPtNodeArray()); final PtNodeArray nodeArray = new PtNodeArray(nodeArrayContents); nodeArray.mCachedAddressBeforeUpdate = nodeArrayOriginPos; diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 106f02519..5cb40f30c 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -61,12 +61,11 @@ public final class BinaryDictIOUtils { /** * Retrieves all node arrays without recursive call. */ - private static void readUnigramsAndBigramsBinaryInner( - final Ver3DictDecoder dictDecoder, final int headerSize, - final Map words, final Map frequencies, + private static void readUnigramsAndBigramsBinaryInner(final DictDecoder dictDecoder, + final int headerSize, final Map words, + final Map frequencies, final Map> bigrams, final FormatOptions formatOptions) { - final DictBuffer dictBuffer = dictDecoder.getDictBuffer(); int[] pushedChars = new int[FormatSpec.MAX_WORD_LENGTH + 1]; Stack stack = new Stack(); @@ -83,11 +82,11 @@ public final class BinaryDictIOUtils { p.mNumOfPtNode + ", position=" + p.mPosition + ", length=" + p.mLength); } - if (dictBuffer.position() != p.mAddress) dictBuffer.position(p.mAddress); + if (dictDecoder.getPosition() != p.mAddress) dictDecoder.setPosition(p.mAddress); if (index != p.mLength) index = p.mLength; if (p.mNumOfPtNode == Position.NOT_READ_PTNODE_COUNT) { - p.mNumOfPtNode = BinaryDictDecoderUtils.readPtNodeCount(dictBuffer); + p.mNumOfPtNode = dictDecoder.readPtNodeCount(); p.mAddress += getPtNodeCountSize(p.mNumOfPtNode); p.mPosition = 0; } @@ -114,11 +113,12 @@ public final class BinaryDictIOUtils { if (p.mPosition == p.mNumOfPtNode) { if (formatOptions.mSupportsDynamicUpdate) { - final int forwardLinkAddress = dictBuffer.readUnsignedInt24(); - if (forwardLinkAddress != FormatSpec.NO_FORWARD_LINK_ADDRESS) { + final boolean hasValidForwardLinkAddress = + dictDecoder.readForwardLinkAndAdvancePosition(); + if (hasValidForwardLinkAddress && dictDecoder.hasNextPtNodeArray()) { // The node array has a forward link. p.mNumOfPtNode = Position.NOT_READ_PTNODE_COUNT; - p.mAddress = forwardLinkAddress; + p.mAddress = dictDecoder.getPosition(); } else { stack.pop(); } @@ -127,7 +127,7 @@ public final class BinaryDictIOUtils { } } else { // The Ptnode array has more PtNodes. - p.mAddress = dictBuffer.position(); + p.mAddress = dictDecoder.getPosition(); } if (!isMovedPtNode && hasChildrenAddress(info.mChildrenAddress)) { @@ -171,9 +171,8 @@ public final class BinaryDictIOUtils { @UsedForTesting /* package */ static int getTerminalPosition(final Ver3DictDecoder dictDecoder, final String word) throws IOException, UnsupportedFormatException { - final DictBuffer dictBuffer = dictDecoder.getDictBuffer(); if (word == null) return FormatSpec.NOT_VALID_WORD; - if (dictBuffer.position() != 0) dictBuffer.position(0); + dictDecoder.setPosition(0); final FileHeader header = dictDecoder.readHeader(); int wordPos = 0; @@ -182,10 +181,10 @@ public final class BinaryDictIOUtils { if (wordPos >= wordLen) return FormatSpec.NOT_VALID_WORD; do { - final int ptNodeCount = BinaryDictDecoderUtils.readPtNodeCount(dictBuffer); + final int ptNodeCount = dictDecoder.readPtNodeCount(); boolean foundNextPtNode = false; for (int i = 0; i < ptNodeCount; ++i) { - final int ptNodePos = dictBuffer.position(); + final int ptNodePos = dictDecoder.getPosition(); final PtNodeInfo currentInfo = dictDecoder.readPtNode(ptNodePos, header.mFormatOptions); final boolean isMovedNode = isMovedPtNode(currentInfo.mFlags, @@ -219,7 +218,7 @@ public final class BinaryDictIOUtils { return FormatSpec.NOT_VALID_WORD; } foundNextPtNode = true; - dictBuffer.position(currentInfo.mChildrenAddress); + dictDecoder.setPosition(currentInfo.mChildrenAddress); break; } } @@ -233,11 +232,11 @@ public final class BinaryDictIOUtils { return FormatSpec.NOT_VALID_WORD; } - final int forwardLinkAddress = dictBuffer.readUnsignedInt24(); - if (forwardLinkAddress == FormatSpec.NO_FORWARD_LINK_ADDRESS) { + final boolean hasValidForwardLinkAddress = + dictDecoder.readForwardLinkAndAdvancePosition(); + if (!hasValidForwardLinkAddress || !dictDecoder.hasNextPtNodeArray()) { return FormatSpec.NOT_VALID_WORD; } - dictBuffer.position(forwardLinkAddress); } while(true); } return FormatSpec.NOT_VALID_WORD; diff --git a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java index 64638fd98..5e398bd41 100644 --- a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java @@ -91,6 +91,33 @@ public interface DictDecoder { final TreeMap> bigrams) throws IOException, UnsupportedFormatException; + /** + * Sets the position of the buffer to the given value. + * + * @param newPos the new position + */ + public void setPosition(final int newPos); + + /** + * Gets the position of the buffer. + * + * @return the position + */ + public int getPosition(); + + /** + * Reads and returns the PtNode count out of a buffer and forwards the pointer. + */ + public int readPtNodeCount(); + + /** + * Reads the forward link and advances the position. + * + * @return if this method advances the position then true else false. + */ + public boolean readForwardLinkAndAdvancePosition(); + public boolean hasNextPtNodeArray(); + // Flags for DictionaryBufferFactory. public static final int USE_READONLY_BYTEBUFFER = 0x01000000; public static final int USE_BYTEARRAY = 0x02000000; diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java index b98aa0f60..6dff9b6d2 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java @@ -348,4 +348,33 @@ public class Ver3DictDecoder implements DictDecoder { BinaryDictIOUtils.readUnigramsAndBigramsBinary(this, words, frequencies, bigrams); } + @Override + public void setPosition(int newPos) { + mDictBuffer.position(newPos); + } + + @Override + public int getPosition() { + return mDictBuffer.position(); + } + + @Override + public int readPtNodeCount() { + return BinaryDictDecoderUtils.readPtNodeCount(mDictBuffer); + } + + @Override + public boolean readForwardLinkAndAdvancePosition() { + final int nextAddress = mDictBuffer.readUnsignedInt24(); + if (nextAddress >= 0 && nextAddress < mDictBuffer.limit()) { + mDictBuffer.position(nextAddress); + return true; + } + return false; + } + + @Override + public boolean hasNextPtNodeArray() { + return mDictBuffer.position() != FormatSpec.NO_FORWARD_LINK_ADDRESS; + } }