GC step 4. Update all positions in new dict and add a test.
Bug: 6669677 Change-Id: I035d848a210653dcd3c1a1f21781968adced9225main
parent
0355bf2d4c
commit
2cfe7f9e3b
|
@ -101,10 +101,13 @@ const int BigramListReadWriteUtils::ATTRIBUTE_ADDRESS_SHIFT = 4;
|
||||||
/* static */ bool BigramListReadWriteUtils::writeBigramEntry(
|
/* static */ bool BigramListReadWriteUtils::writeBigramEntry(
|
||||||
BufferWithExtendableBuffer *const bufferToWrite, const BigramFlags flags,
|
BufferWithExtendableBuffer *const bufferToWrite, const BigramFlags flags,
|
||||||
const int targetPtNodePos, int *const writingPos) {
|
const int targetPtNodePos, int *const writingPos) {
|
||||||
if (!bufferToWrite->writeUintAndAdvancePosition(flags, 1 /* size */, writingPos)) {
|
const int offset = (targetPtNodePos != NOT_A_DICT_POS) ?
|
||||||
|
targetPtNodePos - (*writingPos + 1) : 0;
|
||||||
|
const BigramFlags flagsToWrite = (offset < 0) ?
|
||||||
|
(flags | FLAG_ATTRIBUTE_OFFSET_NEGATIVE) : flags;
|
||||||
|
if (!bufferToWrite->writeUintAndAdvancePosition(flagsToWrite, 1 /* size */, writingPos)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const int offset = (targetPtNodePos != NOT_A_DICT_POS) ? targetPtNodePos - *writingPos : 0;
|
|
||||||
const uint32_t absOffest = abs(offset);
|
const uint32_t absOffest = abs(offset);
|
||||||
const int bigramTargetFieldSize = attributeAddressSize(flags);
|
const int bigramTargetFieldSize = attributeAddressSize(flags);
|
||||||
return bufferToWrite->writeUintAndAdvancePosition(absOffest, bigramTargetFieldSize,
|
return bufferToWrite->writeUintAndAdvancePosition(absOffest, bigramTargetFieldSize,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
|
#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
|
||||||
#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h"
|
#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h"
|
||||||
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
|
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
|
||||||
|
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
|
||||||
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
|
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
@ -71,7 +72,8 @@ bool DynamicBigramListPolicy::copyAllBigrams(BufferWithExtendableBuffer *const b
|
||||||
int bigramEntryCount = 0;
|
int bigramEntryCount = 0;
|
||||||
do {
|
do {
|
||||||
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
||||||
AKLOGE("Too many bigram entries. %d", BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
AKLOGE("Too many bigram entries. Entry count: %d, Limit: %d",
|
||||||
|
bigramEntryCount, BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +116,8 @@ bool DynamicBigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(
|
||||||
int bigramEntryCount = 0;
|
int bigramEntryCount = 0;
|
||||||
do {
|
do {
|
||||||
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
||||||
AKLOGE("Too many bigram entries. %d", BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
AKLOGE("Too many bigram entries. Entry count: %d, Limit: %d",
|
||||||
|
bigramEntryCount, BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -150,6 +153,54 @@ bool DynamicBigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updates bigram target PtNode positions in the list after the placing step in GC.
|
||||||
|
bool DynamicBigramListPolicy::updateAllBigramTargetPtNodePositions(int *const bigramListPos,
|
||||||
|
const DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap *const
|
||||||
|
ptNodePositionRelocationMap) {
|
||||||
|
const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*bigramListPos);
|
||||||
|
if (usesAdditionalBuffer) {
|
||||||
|
*bigramListPos -= mBuffer->getOriginalBufferSize();
|
||||||
|
}
|
||||||
|
BigramListReadWriteUtils::BigramFlags bigramFlags;
|
||||||
|
int bigramEntryCount = 0;
|
||||||
|
do {
|
||||||
|
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
||||||
|
AKLOGE("Too many bigram entries. Entry count: %d, Limit: %d",
|
||||||
|
bigramEntryCount, BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
||||||
|
ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int bigramEntryPos = *bigramListPos;
|
||||||
|
if (usesAdditionalBuffer) {
|
||||||
|
bigramEntryPos += mBuffer->getOriginalBufferSize();
|
||||||
|
}
|
||||||
|
int bigramTargetPtNodePos;
|
||||||
|
// The buffer address can be changed after calling buffer writing methods.
|
||||||
|
BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(
|
||||||
|
mBuffer->getBuffer(usesAdditionalBuffer), &bigramFlags, &bigramTargetPtNodePos,
|
||||||
|
bigramListPos);
|
||||||
|
if (bigramTargetPtNodePos == NOT_A_DICT_POS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (usesAdditionalBuffer) {
|
||||||
|
bigramTargetPtNodePos += mBuffer->getOriginalBufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap::const_iterator it =
|
||||||
|
ptNodePositionRelocationMap->find(bigramTargetPtNodePos);
|
||||||
|
if (it != ptNodePositionRelocationMap->end()) {
|
||||||
|
bigramTargetPtNodePos = it->second;
|
||||||
|
} else {
|
||||||
|
bigramTargetPtNodePos = NOT_A_DICT_POS;
|
||||||
|
}
|
||||||
|
if (!BigramListReadWriteUtils::writeBigramEntry(mBuffer, bigramFlags,
|
||||||
|
bigramTargetPtNodePos, &bigramEntryPos)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while(BigramListReadWriteUtils::hasNext(bigramFlags));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool DynamicBigramListPolicy::addNewBigramEntryToBigramList(const int bigramTargetPos,
|
bool DynamicBigramListPolicy::addNewBigramEntryToBigramList(const int bigramTargetPos,
|
||||||
const int probability, int *const bigramListPos) {
|
const int probability, int *const bigramListPos) {
|
||||||
const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*bigramListPos);
|
const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*bigramListPos);
|
||||||
|
@ -160,7 +211,8 @@ bool DynamicBigramListPolicy::addNewBigramEntryToBigramList(const int bigramTarg
|
||||||
int bigramEntryCount = 0;
|
int bigramEntryCount = 0;
|
||||||
do {
|
do {
|
||||||
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
||||||
AKLOGE("Too many bigram entries. %d", BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
AKLOGE("Too many bigram entries. Entry count: %d, Limit: %d",
|
||||||
|
bigramEntryCount, BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +274,8 @@ bool DynamicBigramListPolicy::removeBigram(const int bigramListPos, const int bi
|
||||||
int bigramEntryCount = 0;
|
int bigramEntryCount = 0;
|
||||||
do {
|
do {
|
||||||
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
if (++bigramEntryCount > BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT) {
|
||||||
AKLOGE("Too many bigram entries. %d", BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
AKLOGE("Too many bigram entries. Entry count: %d, Limit: %d",
|
||||||
|
bigramEntryCount, BIGRAM_ENTRY_COUNT_IN_A_BIGRAM_LIST_LIMIT);
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
|
#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
|
||||||
|
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
|
@ -51,6 +52,10 @@ class DynamicBigramListPolicy : public DictionaryBigramsStructurePolicy {
|
||||||
|
|
||||||
bool updateAllBigramEntriesAndDeleteUselessEntries(int *const bigramListPos);
|
bool updateAllBigramEntriesAndDeleteUselessEntries(int *const bigramListPos);
|
||||||
|
|
||||||
|
bool updateAllBigramTargetPtNodePositions(int *const bigramListPos,
|
||||||
|
const DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap *const
|
||||||
|
ptNodePositionRelocationMap);
|
||||||
|
|
||||||
bool addNewBigramEntryToBigramList(const int bigramTargetPos, const int probability,
|
bool addNewBigramEntryToBigramList(const int bigramTargetPos, const int probability,
|
||||||
int *const bigramListPos);
|
int *const bigramListPos);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
bool DynamicPatriciaTrieGcEventListeners
|
bool DynamicPatriciaTrieGcEventListeners
|
||||||
::ListenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted
|
::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
|
||||||
::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
||||||
const int *const nodeCodePoints) {
|
const int *const nodeCodePoints) {
|
||||||
// PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
|
// PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
|
||||||
|
@ -47,11 +47,13 @@ bool DynamicPatriciaTrieGcEventListeners
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes dummy PtNode array size when the head of PtNode array is read.
|
// Writes dummy PtNode array size when the head of PtNode array is read.
|
||||||
bool DynamicPatriciaTrieGcEventListeners::ListenerForPlacingAndWritingValidPtNodesToBuffer
|
bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
|
||||||
::onDescend(const int ptNodeArrayPos) {
|
::onDescend(const int ptNodeArrayPos) {
|
||||||
mValidPtNodeCount = 0;
|
mValidPtNodeCount = 0;
|
||||||
int writingPos = mBufferToWrite->getTailPosition();
|
int writingPos = mBufferToWrite->getTailPosition();
|
||||||
mPositionMap->insert(hash_map_compat<int, int>::value_type(ptNodeArrayPos, writingPos));
|
mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.insert(
|
||||||
|
DynamicPatriciaTrieWritingHelper::PtNodeArrayPositionRelocationMap::value_type(
|
||||||
|
ptNodeArrayPos, writingPos));
|
||||||
// Writes dummy PtNode array size because arrays can have a forward link or needles PtNodes.
|
// Writes dummy PtNode array size because arrays can have a forward link or needles PtNodes.
|
||||||
// This field will be updated later in onReadingPtNodeArrayTail() with actual PtNode count.
|
// This field will be updated later in onReadingPtNodeArrayTail() with actual PtNode count.
|
||||||
mPtNodeArraySizeFieldPos = writingPos;
|
mPtNodeArraySizeFieldPos = writingPos;
|
||||||
|
@ -60,7 +62,7 @@ bool DynamicPatriciaTrieGcEventListeners::ListenerForPlacingAndWritingValidPtNod
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write PtNode array terminal and actual PtNode array size.
|
// Write PtNode array terminal and actual PtNode array size.
|
||||||
bool DynamicPatriciaTrieGcEventListeners::ListenerForPlacingAndWritingValidPtNodesToBuffer
|
bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
|
||||||
::onReadingPtNodeArrayTail() {
|
::onReadingPtNodeArrayTail() {
|
||||||
int writingPos = mBufferToWrite->getTailPosition();
|
int writingPos = mBufferToWrite->getTailPosition();
|
||||||
// Write PtNode array terminal.
|
// Write PtNode array terminal.
|
||||||
|
@ -77,17 +79,20 @@ bool DynamicPatriciaTrieGcEventListeners::ListenerForPlacingAndWritingValidPtNod
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write valid PtNode to buffer and memorize mapping from the old position to the new position.
|
// Write valid PtNode to buffer and memorize mapping from the old position to the new position.
|
||||||
bool DynamicPatriciaTrieGcEventListeners::ListenerForPlacingAndWritingValidPtNodesToBuffer
|
bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
|
||||||
::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
||||||
const int *const nodeCodePoints) {
|
const int *const nodeCodePoints) {
|
||||||
if (node->isDeleted()) {
|
if (node->isDeleted()) {
|
||||||
// Current PtNode is not written in new buffer because it has been deleted.
|
// Current PtNode is not written in new buffer because it has been deleted.
|
||||||
mPositionMap->insert(hash_map_compat<int, int>::value_type(node->getHeadPos(),
|
mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
|
||||||
NOT_A_DICT_POS));
|
DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap::value_type(
|
||||||
|
node->getHeadPos(), NOT_A_DICT_POS));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int writingPos = mBufferToWrite->getTailPosition();
|
int writingPos = mBufferToWrite->getTailPosition();
|
||||||
mPositionMap->insert(hash_map_compat<int, int>::value_type(node->getHeadPos(), writingPos));
|
mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
|
||||||
|
DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap::value_type(
|
||||||
|
node->getHeadPos(), writingPos));
|
||||||
mValidPtNodeCount++;
|
mValidPtNodeCount++;
|
||||||
// Writes current PtNode.
|
// Writes current PtNode.
|
||||||
return mWritingHelper->writePtNodeToBufferByCopyingPtNodeInfo(mBufferToWrite, node,
|
return mWritingHelper->writePtNodeToBufferByCopyingPtNodeInfo(mBufferToWrite, node,
|
||||||
|
@ -95,4 +100,50 @@ bool DynamicPatriciaTrieGcEventListeners::ListenerForPlacingAndWritingValidPtNod
|
||||||
node->getProbability(), &writingPos);
|
node->getProbability(), &writingPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionFields
|
||||||
|
::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
||||||
|
const int *const nodeCodePoints) {
|
||||||
|
// Updates parent position.
|
||||||
|
int parentPos = node->getParentPos();
|
||||||
|
if (parentPos != NOT_A_DICT_POS) {
|
||||||
|
DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap::const_iterator it =
|
||||||
|
mDictPositionRelocationMap->mPtNodePositionRelocationMap.find(parentPos);
|
||||||
|
if (it != mDictPositionRelocationMap->mPtNodePositionRelocationMap.end()) {
|
||||||
|
parentPos = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int writingPos = node->getHeadPos() + DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE;
|
||||||
|
const int parentPosOffset = (parentPos != NOT_A_DICT_POS) ?
|
||||||
|
parentPos - node->getHeadPos() : NOT_A_DICT_POS;
|
||||||
|
// Write updated parent offset.
|
||||||
|
if (!DynamicPatriciaTrieWritingUtils::writeParentOffsetAndAdvancePosition(mBufferToWrite,
|
||||||
|
parentPosOffset, &writingPos)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates children position.
|
||||||
|
int childrenPos = node->getChildrenPos();
|
||||||
|
if (childrenPos != NOT_A_DICT_POS) {
|
||||||
|
DynamicPatriciaTrieWritingHelper::PtNodeArrayPositionRelocationMap::const_iterator it =
|
||||||
|
mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.find(childrenPos);
|
||||||
|
if (it != mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.end()) {
|
||||||
|
childrenPos = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writingPos = node->getChildrenPosFieldPos();
|
||||||
|
if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBufferToWrite,
|
||||||
|
childrenPos, &writingPos)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates bigram target PtNode positions in the bigram list.
|
||||||
|
int bigramsPos = node->getBigramsPos();
|
||||||
|
if (bigramsPos != NOT_A_DICT_POS) {
|
||||||
|
mBigramPolicy->updateAllBigramTargetPtNodePositions(&bigramsPos,
|
||||||
|
&mDictPositionRelocationMap->mPtNodePositionRelocationMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace latinime
|
} // namespace latinime
|
||||||
|
|
|
@ -34,16 +34,16 @@ class DynamicPatriciaTrieGcEventListeners {
|
||||||
// Updates all PtNodes that can be reached from the root. Checks if each PtNode is useless or
|
// Updates all PtNodes that can be reached from the root. Checks if each PtNode is useless or
|
||||||
// not and marks useless PtNodes as deleted. Such deleted PtNodes will be discarded in the GC.
|
// not and marks useless PtNodes as deleted. Such deleted PtNodes will be discarded in the GC.
|
||||||
// TODO: Concatenate non-terminal PtNodes.
|
// TODO: Concatenate non-terminal PtNodes.
|
||||||
class ListenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted
|
class TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
|
||||||
: public DynamicPatriciaTrieReadingHelper::TraversingEventListener {
|
: public DynamicPatriciaTrieReadingHelper::TraversingEventListener {
|
||||||
public:
|
public:
|
||||||
ListenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted(
|
TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
|
||||||
DynamicPatriciaTrieWritingHelper *const writingHelper,
|
DynamicPatriciaTrieWritingHelper *const writingHelper,
|
||||||
BufferWithExtendableBuffer *const buffer)
|
BufferWithExtendableBuffer *const buffer)
|
||||||
: mWritingHelper(writingHelper), mBuffer(buffer), valueStack(),
|
: mWritingHelper(writingHelper), mBuffer(buffer), valueStack(),
|
||||||
mChildrenValue(0) {}
|
mChildrenValue(0) {}
|
||||||
|
|
||||||
~ListenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted() {};
|
~TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted() {};
|
||||||
|
|
||||||
bool onAscend() {
|
bool onAscend() {
|
||||||
if (valueStack.empty()) {
|
if (valueStack.empty()) {
|
||||||
|
@ -66,7 +66,7 @@ class DynamicPatriciaTrieGcEventListeners {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(
|
DISALLOW_IMPLICIT_CONSTRUCTORS(
|
||||||
ListenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted);
|
TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted);
|
||||||
|
|
||||||
DynamicPatriciaTrieWritingHelper *const mWritingHelper;
|
DynamicPatriciaTrieWritingHelper *const mWritingHelper;
|
||||||
BufferWithExtendableBuffer *const mBuffer;
|
BufferWithExtendableBuffer *const mBuffer;
|
||||||
|
@ -76,10 +76,10 @@ class DynamicPatriciaTrieGcEventListeners {
|
||||||
|
|
||||||
// Updates all bigram entries that are held by valid PtNodes. This removes useless bigram
|
// Updates all bigram entries that are held by valid PtNodes. This removes useless bigram
|
||||||
// entries.
|
// entries.
|
||||||
class ListenerForUpdatingBigramProbability
|
class TraversePolicyToUpdateBigramProbability
|
||||||
: public DynamicPatriciaTrieReadingHelper::TraversingEventListener {
|
: public DynamicPatriciaTrieReadingHelper::TraversingEventListener {
|
||||||
public:
|
public:
|
||||||
ListenerForUpdatingBigramProbability(DynamicBigramListPolicy *const bigramPolicy)
|
TraversePolicyToUpdateBigramProbability(DynamicBigramListPolicy *const bigramPolicy)
|
||||||
: mBigramPolicy(bigramPolicy) {}
|
: mBigramPolicy(bigramPolicy) {}
|
||||||
|
|
||||||
bool onAscend() { return true; }
|
bool onAscend() { return true; }
|
||||||
|
@ -102,20 +102,21 @@ class DynamicPatriciaTrieGcEventListeners {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ListenerForUpdatingBigramProbability);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateBigramProbability);
|
||||||
|
|
||||||
DynamicBigramListPolicy *const mBigramPolicy;
|
DynamicBigramListPolicy *const mBigramPolicy;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ListenerForPlacingAndWritingValidPtNodesToBuffer
|
class TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
|
||||||
: public DynamicPatriciaTrieReadingHelper::TraversingEventListener {
|
: public DynamicPatriciaTrieReadingHelper::TraversingEventListener {
|
||||||
public:
|
public:
|
||||||
ListenerForPlacingAndWritingValidPtNodesToBuffer(
|
TraversePolicyToPlaceAndWriteValidPtNodesToBuffer(
|
||||||
DynamicPatriciaTrieWritingHelper *const writingHelper,
|
DynamicPatriciaTrieWritingHelper *const writingHelper,
|
||||||
BufferWithExtendableBuffer *const bufferToWrite,
|
BufferWithExtendableBuffer *const bufferToWrite,
|
||||||
hash_map_compat<int, int> *const positionMap)
|
DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const
|
||||||
|
dictPositionRelocationMap)
|
||||||
: mWritingHelper(writingHelper), mBufferToWrite(bufferToWrite),
|
: mWritingHelper(writingHelper), mBufferToWrite(bufferToWrite),
|
||||||
mPositionMap(positionMap), mValidPtNodeCount(0),
|
mDictPositionRelocationMap(dictPositionRelocationMap), mValidPtNodeCount(0),
|
||||||
mPtNodeArraySizeFieldPos(NOT_A_DICT_POS) {};
|
mPtNodeArraySizeFieldPos(NOT_A_DICT_POS) {};
|
||||||
|
|
||||||
bool onAscend() { return true; }
|
bool onAscend() { return true; }
|
||||||
|
@ -127,20 +128,49 @@ class DynamicPatriciaTrieGcEventListeners {
|
||||||
bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
||||||
const int *const nodeCodePoints);
|
const int *const nodeCodePoints);
|
||||||
|
|
||||||
hash_map_compat<int, int> *getPositionMap() const {
|
|
||||||
return mPositionMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ListenerForPlacingAndWritingValidPtNodesToBuffer);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToPlaceAndWriteValidPtNodesToBuffer);
|
||||||
|
|
||||||
DynamicPatriciaTrieWritingHelper *const mWritingHelper;
|
DynamicPatriciaTrieWritingHelper *const mWritingHelper;
|
||||||
BufferWithExtendableBuffer *const mBufferToWrite;
|
BufferWithExtendableBuffer *const mBufferToWrite;
|
||||||
hash_map_compat<int, int> *const mPositionMap;
|
DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const
|
||||||
|
mDictPositionRelocationMap;
|
||||||
int mValidPtNodeCount;
|
int mValidPtNodeCount;
|
||||||
int mPtNodeArraySizeFieldPos;
|
int mPtNodeArraySizeFieldPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TraversePolicyToUpdateAllPositionFields
|
||||||
|
: public DynamicPatriciaTrieReadingHelper::TraversingEventListener {
|
||||||
|
public:
|
||||||
|
TraversePolicyToUpdateAllPositionFields(
|
||||||
|
DynamicPatriciaTrieWritingHelper *const writingHelper,
|
||||||
|
DynamicBigramListPolicy *const bigramPolicy,
|
||||||
|
BufferWithExtendableBuffer *const bufferToWrite,
|
||||||
|
const DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const
|
||||||
|
dictPositionRelocationMap)
|
||||||
|
: mWritingHelper(writingHelper), mBigramPolicy(bigramPolicy),
|
||||||
|
mBufferToWrite(bufferToWrite),
|
||||||
|
mDictPositionRelocationMap(dictPositionRelocationMap) {};
|
||||||
|
|
||||||
|
bool onAscend() { return true; }
|
||||||
|
|
||||||
|
bool onDescend(const int ptNodeArrayPos) { return true; }
|
||||||
|
|
||||||
|
bool onReadingPtNodeArrayTail() { return true; }
|
||||||
|
|
||||||
|
bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
|
||||||
|
const int *const nodeCodePoints);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPositionFields);
|
||||||
|
|
||||||
|
DynamicPatriciaTrieWritingHelper *const mWritingHelper;
|
||||||
|
DynamicBigramListPolicy *const mBigramPolicy;
|
||||||
|
BufferWithExtendableBuffer *const mBufferToWrite;
|
||||||
|
const DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const
|
||||||
|
mDictPositionRelocationMap;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTrieGcEventListeners);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTrieGcEventListeners);
|
||||||
};
|
};
|
||||||
|
|
|
@ -258,7 +258,9 @@ void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) {
|
||||||
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
|
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: Implement.
|
DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer,
|
||||||
|
&mBigramListPolicy, &mShortcutListPolicy);
|
||||||
|
writingHelper.writeToDictFileWithGC(getRootPosition(), filePath, &mHeaderPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DynamicPatriciaTriePolicy::needsToRunGC() const {
|
bool DynamicPatriciaTriePolicy::needsToRunGC() const {
|
||||||
|
|
|
@ -59,6 +59,9 @@ bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPostorderDepthFirstMa
|
||||||
if (!listener->onReadingPtNodeArrayTail()) {
|
if (!listener->onReadingPtNodeArrayTail()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (mReadingStateStack.size() <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!listener->onAscend()) {
|
if (!listener->onAscend()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +104,9 @@ bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreor
|
||||||
if (!listener->onAscend()) {
|
if (!listener->onAscend()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (mReadingStateStack.size() <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
popReadingStateFromStack();
|
popReadingStateFromStack();
|
||||||
alreadyVisitedChildren = true;
|
alreadyVisitedChildren = true;
|
||||||
alreadyVisitedAllPtNodesInArray = true;
|
alreadyVisitedAllPtNodesInArray = true;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "suggest/policyimpl/dictionary/header/header_policy.h"
|
#include "suggest/policyimpl/dictionary/header/header_policy.h"
|
||||||
#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
|
#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
|
||||||
#include "suggest/policyimpl/dictionary/shortcut/dynamic_shortcut_list_policy.h"
|
#include "suggest/policyimpl/dictionary/shortcut/dynamic_shortcut_list_policy.h"
|
||||||
|
#include "utils/hash_map_compat.h"
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
|
@ -221,7 +222,8 @@ bool DynamicPatriciaTrieWritingHelper::markNodeAsMovedAndSetPosition(
|
||||||
while (!readingHelper.isEnd()) {
|
while (!readingHelper.isEnd()) {
|
||||||
const int childPtNodeWrittenPos = nodeReader->getHeadPos();
|
const int childPtNodeWrittenPos = nodeReader->getHeadPos();
|
||||||
const int parentOffset = movedPos - childPtNodeWrittenPos;
|
const int parentOffset = movedPos - childPtNodeWrittenPos;
|
||||||
int parentOffsetFieldPos = childPtNodeWrittenPos + 1 /* Flags */;
|
int parentOffsetFieldPos = childPtNodeWrittenPos
|
||||||
|
+ DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE;
|
||||||
if (!DynamicPatriciaTrieWritingUtils::writeParentOffsetAndAdvancePosition(
|
if (!DynamicPatriciaTrieWritingUtils::writeParentOffsetAndAdvancePosition(
|
||||||
mBuffer, parentOffset, &parentOffsetFieldPos)) {
|
mBuffer, parentOffset, &parentOffsetFieldPos)) {
|
||||||
// Parent offset cannot be written because of a bug or a broken dictionary; thus,
|
// Parent offset cannot be written because of a bug or a broken dictionary; thus,
|
||||||
|
@ -521,30 +523,48 @@ bool DynamicPatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
|
||||||
DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy);
|
DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy);
|
||||||
readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
|
readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
|
||||||
DynamicPatriciaTrieGcEventListeners
|
DynamicPatriciaTrieGcEventListeners
|
||||||
::ListenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted
|
::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
|
||||||
listenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted(
|
traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
|
||||||
this, mBuffer);
|
this, mBuffer);
|
||||||
if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
|
if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
|
||||||
&listenerForUpdatingUnigramProbabilityAndMarkingUselessPtNodesAsDeleted)) {
|
&traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
|
readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
|
||||||
DynamicPatriciaTrieGcEventListeners::ListenerForUpdatingBigramProbability
|
DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateBigramProbability
|
||||||
listenerForupdatingBigramProbability(mBigramPolicy);
|
traversePolicyToUpdateBigramProbability(mBigramPolicy);
|
||||||
if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
|
if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
|
||||||
&listenerForupdatingBigramProbability)) {
|
&traversePolicyToUpdateBigramProbability)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mapping from positions in mBuffer to positions in bufferToWrite.
|
// Mapping from positions in mBuffer to positions in bufferToWrite.
|
||||||
hash_map_compat<int, int> positionMap;
|
DictPositionRelocationMap dictPositionRelocationMap;
|
||||||
readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
|
readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
|
||||||
DynamicPatriciaTrieGcEventListeners::ListenerForPlacingAndWritingValidPtNodesToBuffer
|
DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
|
||||||
listenerForPlacingAndWritingLivingPtNodesToBuffer(this, mBuffer, &positionMap);
|
traversePolicyToPlaceAndWriteValidPtNodesToBuffer(this, bufferToWrite,
|
||||||
|
&dictPositionRelocationMap);
|
||||||
// TODO: Implement.
|
if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
|
||||||
|
&traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create policy instance for the GCed dictionary.
|
||||||
|
DynamicShortcutListPolicy newDictShortcutPolicy(bufferToWrite);
|
||||||
|
DynamicBigramListPolicy newDictBigramPolicy(bufferToWrite, &newDictShortcutPolicy);
|
||||||
|
// Create reading helper for the GCed dictionary.
|
||||||
|
DynamicPatriciaTrieReadingHelper newDictReadingHelper(bufferToWrite, &newDictBigramPolicy,
|
||||||
|
&newDictShortcutPolicy);
|
||||||
|
newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
|
||||||
|
DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionFields
|
||||||
|
traversePolicyToUpdateAllPositionFields(this, &newDictBigramPolicy, bufferToWrite,
|
||||||
|
&dictPositionRelocationMap);
|
||||||
|
if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
|
||||||
|
&traversePolicyToUpdateAllPositionFields)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace latinime
|
} // namespace latinime
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
#include "utils/hash_map_compat.h"
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
|
@ -33,6 +34,20 @@ class HeaderPolicy;
|
||||||
|
|
||||||
class DynamicPatriciaTrieWritingHelper {
|
class DynamicPatriciaTrieWritingHelper {
|
||||||
public:
|
public:
|
||||||
|
typedef hash_map_compat<int, int> PtNodeArrayPositionRelocationMap;
|
||||||
|
typedef hash_map_compat<int, int> PtNodePositionRelocationMap;
|
||||||
|
struct DictPositionRelocationMap {
|
||||||
|
public:
|
||||||
|
DictPositionRelocationMap()
|
||||||
|
: mPtNodeArrayPositionRelocationMap(), mPtNodePositionRelocationMap() {}
|
||||||
|
|
||||||
|
PtNodeArrayPositionRelocationMap mPtNodeArrayPositionRelocationMap;
|
||||||
|
PtNodePositionRelocationMap mPtNodePositionRelocationMap;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(DictPositionRelocationMap);
|
||||||
|
};
|
||||||
|
|
||||||
DynamicPatriciaTrieWritingHelper(BufferWithExtendableBuffer *const buffer,
|
DynamicPatriciaTrieWritingHelper(BufferWithExtendableBuffer *const buffer,
|
||||||
DynamicBigramListPolicy *const bigramPolicy,
|
DynamicBigramListPolicy *const bigramPolicy,
|
||||||
DynamicShortcutListPolicy *const shortcutPolicy)
|
DynamicShortcutListPolicy *const shortcutPolicy)
|
||||||
|
|
|
@ -28,6 +28,8 @@ class BufferWithExtendableBuffer;
|
||||||
|
|
||||||
class DynamicPatriciaTrieWritingUtils {
|
class DynamicPatriciaTrieWritingUtils {
|
||||||
public:
|
public:
|
||||||
|
static const int NODE_FLAG_FIELD_SIZE;
|
||||||
|
|
||||||
static bool writeForwardLinkPositionAndAdvancePosition(
|
static bool writeForwardLinkPositionAndAdvancePosition(
|
||||||
BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
|
BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
|
||||||
int *const forwardLinkFieldPos);
|
int *const forwardLinkFieldPos);
|
||||||
|
@ -63,7 +65,6 @@ class DynamicPatriciaTrieWritingUtils {
|
||||||
static const int MAX_DICT_OFFSET_VALUE;
|
static const int MAX_DICT_OFFSET_VALUE;
|
||||||
static const int MIN_DICT_OFFSET_VALUE;
|
static const int MIN_DICT_OFFSET_VALUE;
|
||||||
static const int DICT_OFFSET_NEGATIVE_FLAG;
|
static const int DICT_OFFSET_NEGATIVE_FLAG;
|
||||||
static const int NODE_FLAG_FIELD_SIZE;
|
|
||||||
static const int PROBABILITY_FIELD_SIZE;
|
static const int PROBABILITY_FIELD_SIZE;
|
||||||
|
|
||||||
static bool writeDictOffset(BufferWithExtendableBuffer *const buffer, const int offset,
|
static bool writeDictOffset(BufferWithExtendableBuffer *const buffer, const int offset,
|
||||||
|
|
|
@ -384,4 +384,51 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
||||||
|
|
||||||
dictFile.delete();
|
dictFile.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add large tests for BinaryDictionary.flushWithGC().
|
||||||
|
public void testFlushWithGCDictionary() {
|
||||||
|
File dictFile = null;
|
||||||
|
try {
|
||||||
|
dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("IOException while writing an initial dictionary : " + e);
|
||||||
|
} catch (UnsupportedFormatException e) {
|
||||||
|
fail("UnsupportedFormatException while writing an initial dictionary : " + e);
|
||||||
|
}
|
||||||
|
BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
|
||||||
|
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
||||||
|
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
||||||
|
|
||||||
|
final int unigramProbability = 100;
|
||||||
|
final int bigramProbability = 10;
|
||||||
|
binaryDictionary.addUnigramWord("aaa", unigramProbability);
|
||||||
|
binaryDictionary.addUnigramWord("abb", unigramProbability);
|
||||||
|
binaryDictionary.addUnigramWord("bcc", unigramProbability);
|
||||||
|
binaryDictionary.addBigramWords("aaa", "abb", bigramProbability);
|
||||||
|
binaryDictionary.addBigramWords("aaa", "bcc", bigramProbability);
|
||||||
|
binaryDictionary.addBigramWords("abb", "aaa", bigramProbability);
|
||||||
|
binaryDictionary.addBigramWords("abb", "bcc", bigramProbability);
|
||||||
|
binaryDictionary.flushWithGC();
|
||||||
|
binaryDictionary.close();
|
||||||
|
|
||||||
|
binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
|
||||||
|
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
||||||
|
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
||||||
|
final int probability = binaryDictionary.calculateProbability(unigramProbability,
|
||||||
|
bigramProbability);
|
||||||
|
assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
|
||||||
|
assertEquals(unigramProbability, binaryDictionary.getFrequency("abb"));
|
||||||
|
assertEquals(unigramProbability, binaryDictionary.getFrequency("bcc"));
|
||||||
|
assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "abb"));
|
||||||
|
assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "bcc"));
|
||||||
|
assertEquals(probability, binaryDictionary.getBigramProbability("abb", "aaa"));
|
||||||
|
assertEquals(probability, binaryDictionary.getBigramProbability("abb", "bcc"));
|
||||||
|
assertEquals(false, binaryDictionary.isValidBigram("bcc", "aaa"));
|
||||||
|
assertEquals(false, binaryDictionary.isValidBigram("bcc", "bbc"));
|
||||||
|
assertEquals(false, binaryDictionary.isValidBigram("aaa", "aaa"));
|
||||||
|
binaryDictionary.flushWithGC();
|
||||||
|
binaryDictionary.close();
|
||||||
|
|
||||||
|
dictFile.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue