145 lines
5.9 KiB
C++
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
|