LatinIME/native/jni/src/dictionary/structure/pt_common/dynamic_pt_gc_event_listene...

145 lines
5.9 KiB
C++

/*
* 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 "dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
#include "dictionary/interface/dictionary_header_structure_policy.h"
#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
#include "dictionary/structure/pt_common/pt_node_params.h"
#include "dictionary/structure/pt_common/pt_node_writer.h"
namespace latinime {
bool DynamicPtGcEventListeners
::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
// PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
// children.
bool isUselessPtNode = !ptNodeParams->isTerminal();
if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
bool needsToKeepPtNode = true;
if (!mPtNodeWriter->updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
ptNodeParams, &needsToKeepPtNode)) {
AKLOGE("Cannot update PtNode probability or get needs to keep PtNode after GC.");
return false;
}
if (!needsToKeepPtNode) {
isUselessPtNode = true;
}
}
if (mChildrenValue > 0) {
isUselessPtNode = false;
} else if (ptNodeParams->isTerminal()) {
// Remove children as all children are useless.
if (!mPtNodeWriter->updateChildrenPosition(ptNodeParams,
NOT_A_DICT_POS /* newChildrenPosition */)) {
return false;
}
}
if (isUselessPtNode) {
// Current PtNode is no longer needed. Mark it as deleted.
if (!mPtNodeWriter->markPtNodeAsDeleted(ptNodeParams)) {
return false;
}
} else {
mValueStack.back() += 1;
if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
mValidUnigramCount += 1;
}
}
return true;
}
bool DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
if (!ptNodeParams->isDeleted()) {
int bigramEntryCount = 0;
if (!mPtNodeWriter->updateAllBigramEntriesAndDeleteUselessEntries(ptNodeParams,
&bigramEntryCount)) {
return false;
}
mValidBigramEntryCount += bigramEntryCount;
}
return true;
}
// Writes placeholder PtNode array size when the head of PtNode array is read.
bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
::onDescend(const int ptNodeArrayPos) {
mValidPtNodeCount = 0;
int writingPos = mBufferToWrite->getTailPosition();
mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.insert(
PtNodeWriter::PtNodeArrayPositionRelocationMap::value_type(ptNodeArrayPos, writingPos));
// Writes placeholder 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.
mPtNodeArraySizeFieldPos = writingPos;
return DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
mBufferToWrite, 0 /* arraySize */, &writingPos);
}
// Write PtNode array terminal and actual PtNode array size.
bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
::onReadingPtNodeArrayTail() {
int writingPos = mBufferToWrite->getTailPosition();
// Write PtNode array terminal.
if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(
mBufferToWrite, NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
return false;
}
// Write actual PtNode array size.
if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
mBufferToWrite, mValidPtNodeCount, &mPtNodeArraySizeFieldPos)) {
return false;
}
return true;
}
// Write valid PtNode to buffer and memorize mapping from the old position to the new position.
bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
if (ptNodeParams->isDeleted()) {
// Current PtNode is not written in new buffer because it has been deleted.
mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
PtNodeWriter::PtNodePositionRelocationMap::value_type(
ptNodeParams->getHeadPos(), NOT_A_DICT_POS));
return true;
}
int writingPos = mBufferToWrite->getTailPosition();
mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
PtNodeWriter::PtNodePositionRelocationMap::value_type(
ptNodeParams->getHeadPos(), writingPos));
mValidPtNodeCount++;
// Writes current PtNode.
return mPtNodeWriter->writePtNodeAndAdvancePosition(ptNodeParams, &writingPos);
}
bool DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
// Updates parent position.
int bigramCount = 0;
if (!mPtNodeWriter->updateAllPositionFields(ptNodeParams, mDictPositionRelocationMap,
&bigramCount)) {
return false;
}
mBigramCount += bigramCount;
if (ptNodeParams->isTerminal()) {
mUnigramCount++;
}
return true;
}
} // namespace latinime