1/* 2 * Copyright (C) 2014 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 "offdevice_intermediate_dict/offdevice_intermediate_dict.h" 18 19#include "offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node.h" 20 21namespace latinime { 22namespace dicttoolkit { 23 24bool OffdeviceIntermediateDict::addWord(const WordProperty &wordProperty) { 25 const CodePointArrayView codePoints = wordProperty.getCodePoints(); 26 if (codePoints.empty() || codePoints.size() > MAX_WORD_LENGTH) { 27 return false; 28 } 29 return addWordInner(codePoints, wordProperty, mRootPtNodeArray); 30} 31 32bool OffdeviceIntermediateDict::addWordInner(const CodePointArrayView codePoints, 33 const WordProperty &wordProperty, OffdeviceIntermediateDictPtNodeArray &ptNodeArray) { 34 auto ptNodeList = ptNodeArray.getMutablePtNodeList(); 35 auto ptNodeIt = ptNodeList->begin(); 36 for (; ptNodeIt != ptNodeList->end(); ++ptNodeIt) { 37 const auto &ptNode = *ptNodeIt; 38 const CodePointArrayView ptNodeCodePoints = ptNode->getPtNodeCodePoints(); 39 if (codePoints[0] < ptNodeCodePoints[0]) { 40 continue; 41 } 42 if (codePoints[0] > ptNodeCodePoints[0]) { 43 break; 44 } 45 size_t i = 1; 46 for (; i < codePoints.size(); ++i) { 47 if (i >= ptNodeCodePoints.size()) { 48 // Add new child. 49 return addWordInner(codePoints.skip(i), wordProperty, 50 ptNode->getChildrenPtNodeArray()); 51 } 52 if (codePoints[i] != ptNodeCodePoints[i]) { 53 break; 54 } 55 } 56 if (codePoints.size() == i && codePoints.size() == ptNodeCodePoints.size()) { 57 // All code points matched. 58 if (ptNode->getWordProperty()) { 59 // Adding the same word multiple times is not supported. 60 return false; 61 } 62 ptNodeList->insert(ptNodeIt, 63 std::make_shared<OffdeviceIntermediateDictPtNode>(wordProperty, *ptNode)); 64 ptNodeList->erase(ptNodeIt); 65 return true; 66 } 67 // The (i+1)-th elements are different. 68 // Create and Add new parent ptNode for the common part. 69 auto newPtNode = codePoints.size() == i 70 ? std::make_shared<OffdeviceIntermediateDictPtNode>(codePoints, wordProperty) 71 : std::make_shared<OffdeviceIntermediateDictPtNode>(codePoints.limit(i)); 72 ptNodeList->insert(ptNodeIt, newPtNode); 73 OffdeviceIntermediateDictPtNodeArray &childrenPtNodeArray = 74 newPtNode->getChildrenPtNodeArray(); 75 // Add new child for the existing ptNode. 76 childrenPtNodeArray.getMutablePtNodeList()->push_back( 77 std::make_shared<OffdeviceIntermediateDictPtNode>( 78 ptNodeCodePoints.skip(i), *ptNode)); 79 ptNodeList->erase(ptNodeIt); 80 if (codePoints.size() != i) { 81 // Add a child for the new word. 82 return addWordInner(codePoints.skip(i), wordProperty, childrenPtNodeArray); 83 } 84 return true; 85 } 86 ptNodeList->insert(ptNodeIt, 87 std::make_shared<OffdeviceIntermediateDictPtNode>(codePoints, wordProperty)); 88 return true; 89} 90 91const WordProperty *OffdeviceIntermediateDict::getWordProperty( 92 const CodePointArrayView codePoints) const { 93 const OffdeviceIntermediateDictPtNodeArray *ptNodeArray = &mRootPtNodeArray; 94 for (size_t i = 0; i < codePoints.size();) { 95 bool foundNext = false; 96 for (const auto ptNode : ptNodeArray->getPtNodeList()) { 97 const CodePointArrayView ptNodeCodePoints = ptNode->getPtNodeCodePoints(); 98 if (codePoints[i] < ptNodeCodePoints[0]) { 99 continue; 100 } 101 if (codePoints[i] > ptNodeCodePoints[0] 102 || codePoints.size() < ptNodeCodePoints.size()) { 103 return nullptr; 104 } 105 for (size_t j = 1; j < ptNodeCodePoints.size(); ++j) { 106 if (codePoints[i + j] != ptNodeCodePoints[j]) { 107 return nullptr; 108 } 109 } 110 i += ptNodeCodePoints.size(); 111 if (i == codePoints.size()) { 112 return ptNode->getWordProperty(); 113 } 114 ptNodeArray = &ptNode->getChildrenPtNodeArray(); 115 foundNext = true; 116 break; 117 } 118 if (!foundNext) { 119 break; 120 } 121 } 122 return nullptr; 123} 124 125} // namespace dicttoolkit 126} // namespace latinime 127