Home | History | Annotate | Download | only in pt_common
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
     18 
     19 #include "dictionary/interface/dictionary_header_structure_policy.h"
     20 #include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
     21 #include "dictionary/structure/pt_common/pt_node_params.h"
     22 #include "dictionary/structure/pt_common/pt_node_writer.h"
     23 
     24 namespace latinime {
     25 
     26 bool DynamicPtGcEventListeners
     27         ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
     28                 ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
     29     // PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
     30     // children.
     31     bool isUselessPtNode = !ptNodeParams->isTerminal();
     32     if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
     33         bool needsToKeepPtNode = true;
     34         if (!mPtNodeWriter->updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
     35                 ptNodeParams, &needsToKeepPtNode)) {
     36             AKLOGE("Cannot update PtNode probability or get needs to keep PtNode after GC.");
     37             return false;
     38         }
     39         if (!needsToKeepPtNode) {
     40             isUselessPtNode = true;
     41         }
     42     }
     43     if (mChildrenValue > 0) {
     44         isUselessPtNode = false;
     45     } else if (ptNodeParams->isTerminal()) {
     46         // Remove children as all children are useless.
     47         if (!mPtNodeWriter->updateChildrenPosition(ptNodeParams,
     48                 NOT_A_DICT_POS /* newChildrenPosition */)) {
     49             return false;
     50         }
     51     }
     52     if (isUselessPtNode) {
     53         // Current PtNode is no longer needed. Mark it as deleted.
     54         if (!mPtNodeWriter->markPtNodeAsDeleted(ptNodeParams)) {
     55             return false;
     56         }
     57     } else {
     58         mValueStack.back() += 1;
     59         if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
     60             mValidUnigramCount += 1;
     61         }
     62     }
     63     return true;
     64 }
     65 
     66 bool DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
     67         ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
     68     if (!ptNodeParams->isDeleted()) {
     69         int bigramEntryCount = 0;
     70         if (!mPtNodeWriter->updateAllBigramEntriesAndDeleteUselessEntries(ptNodeParams,
     71                 &bigramEntryCount)) {
     72             return false;
     73         }
     74         mValidBigramEntryCount += bigramEntryCount;
     75     }
     76     return true;
     77 }
     78 
     79 // Writes dummy PtNode array size when the head of PtNode array is read.
     80 bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
     81         ::onDescend(const int ptNodeArrayPos) {
     82     mValidPtNodeCount = 0;
     83     int writingPos = mBufferToWrite->getTailPosition();
     84     mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.insert(
     85             PtNodeWriter::PtNodeArrayPositionRelocationMap::value_type(ptNodeArrayPos, writingPos));
     86     // Writes dummy PtNode array size because arrays can have a forward link or needles PtNodes.
     87     // This field will be updated later in onReadingPtNodeArrayTail() with actual PtNode count.
     88     mPtNodeArraySizeFieldPos = writingPos;
     89     return DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
     90             mBufferToWrite, 0 /* arraySize */, &writingPos);
     91 }
     92 
     93 // Write PtNode array terminal and actual PtNode array size.
     94 bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
     95         ::onReadingPtNodeArrayTail() {
     96     int writingPos = mBufferToWrite->getTailPosition();
     97     // Write PtNode array terminal.
     98     if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(
     99             mBufferToWrite, NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
    100         return false;
    101     }
    102     // Write actual PtNode array size.
    103     if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
    104             mBufferToWrite, mValidPtNodeCount, &mPtNodeArraySizeFieldPos)) {
    105         return false;
    106     }
    107     return true;
    108 }
    109 
    110 // Write valid PtNode to buffer and memorize mapping from the old position to the new position.
    111 bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
    112         ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
    113     if (ptNodeParams->isDeleted()) {
    114         // Current PtNode is not written in new buffer because it has been deleted.
    115         mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
    116                 PtNodeWriter::PtNodePositionRelocationMap::value_type(
    117                         ptNodeParams->getHeadPos(), NOT_A_DICT_POS));
    118         return true;
    119     }
    120     int writingPos = mBufferToWrite->getTailPosition();
    121     mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
    122             PtNodeWriter::PtNodePositionRelocationMap::value_type(
    123                     ptNodeParams->getHeadPos(), writingPos));
    124     mValidPtNodeCount++;
    125     // Writes current PtNode.
    126     return mPtNodeWriter->writePtNodeAndAdvancePosition(ptNodeParams, &writingPos);
    127 }
    128 
    129 bool DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
    130         ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
    131     // Updates parent position.
    132     int bigramCount = 0;
    133     if (!mPtNodeWriter->updateAllPositionFields(ptNodeParams, mDictPositionRelocationMap,
    134             &bigramCount)) {
    135         return false;
    136     }
    137     mBigramCount += bigramCount;
    138     if (ptNodeParams->isTerminal()) {
    139         mUnigramCount++;
    140     }
    141     return true;
    142 }
    143 
    144 } // namespace latinime
    145