| Index: third_party/android_prediction/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
|
| diff --git a/third_party/android_prediction/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h b/third_party/android_prediction/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c6a609198ea6de5ad26c67e6e301c114c2878686
|
| --- /dev/null
|
| +++ b/third_party/android_prediction/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
|
| @@ -0,0 +1,283 @@
|
| +/*
|
| + * 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.
|
| + */
|
| +
|
| +#ifndef LATINIME_DYNAMIC_PT_READING_HELPER_H
|
| +#define LATINIME_DYNAMIC_PT_READING_HELPER_H
|
| +
|
| +#include <cstddef>
|
| +#include <vector>
|
| +
|
| +#include "third_party/android_prediction/defines.h"
|
| +#include "third_party/android_prediction/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
|
| +#include "third_party/android_prediction/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
|
| +
|
| +namespace latinime {
|
| +
|
| +class DictionaryShortcutsStructurePolicy;
|
| +class PtNodeArrayReader;
|
| +
|
| +/*
|
| + * This class is used for traversing dynamic patricia trie. This class supports iterating nodes and
|
| + * dealing with additional buffer. This class counts nodes and node arrays to avoid infinite loop.
|
| + */
|
| +class DynamicPtReadingHelper {
|
| + public:
|
| + class TraversingEventListener {
|
| + public:
|
| + virtual ~TraversingEventListener() {};
|
| +
|
| + // Returns whether the event handling was succeeded or not.
|
| + virtual bool onAscend() = 0;
|
| +
|
| + // Returns whether the event handling was succeeded or not.
|
| + virtual bool onDescend(const int ptNodeArrayPos) = 0;
|
| +
|
| + // Returns whether the event handling was succeeded or not.
|
| + virtual bool onReadingPtNodeArrayTail() = 0;
|
| +
|
| + // Returns whether the event handling was succeeded or not.
|
| + virtual bool onVisitingPtNode(const PtNodeParams *const node) = 0;
|
| +
|
| + protected:
|
| + TraversingEventListener() {};
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(TraversingEventListener);
|
| + };
|
| +
|
| + class TraversePolicyToGetAllTerminalPtNodePositions : public TraversingEventListener {
|
| + public:
|
| + TraversePolicyToGetAllTerminalPtNodePositions(std::vector<int> *const terminalPositions)
|
| + : mTerminalPositions(terminalPositions) {}
|
| + bool onAscend() { return true; }
|
| + bool onDescend(const int ptNodeArrayPos) { return true; }
|
| + bool onReadingPtNodeArrayTail() { return true; }
|
| + bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
|
| +
|
| + private:
|
| + DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToGetAllTerminalPtNodePositions);
|
| +
|
| + std::vector<int> *const mTerminalPositions;
|
| + };
|
| +
|
| + DynamicPtReadingHelper(const PtNodeReader *const ptNodeReader,
|
| + const PtNodeArrayReader *const ptNodeArrayReader)
|
| + : mIsError(false), mReadingState(), mPtNodeReader(ptNodeReader),
|
| + mPtNodeArrayReader(ptNodeArrayReader), mReadingStateStack() {}
|
| +
|
| + ~DynamicPtReadingHelper() {}
|
| +
|
| + AK_FORCE_INLINE bool isError() const {
|
| + return mIsError;
|
| + }
|
| +
|
| + AK_FORCE_INLINE bool isEnd() const {
|
| + return mReadingState.mPos == NOT_A_DICT_POS;
|
| + }
|
| +
|
| + // Initialize reading state with the head position of a PtNode array.
|
| + AK_FORCE_INLINE void initWithPtNodeArrayPos(const int ptNodeArrayPos) {
|
| + if (ptNodeArrayPos == NOT_A_DICT_POS) {
|
| + mReadingState.mPos = NOT_A_DICT_POS;
|
| + } else {
|
| + mIsError = false;
|
| + mReadingState.mPos = ptNodeArrayPos;
|
| + mReadingState.mTotalCodePointCountSinceInitialization = 0;
|
| + mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
|
| + mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
|
| + mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
|
| + mReadingStateStack.clear();
|
| + nextPtNodeArray();
|
| + }
|
| + }
|
| +
|
| + // Initialize reading state with the head position of a node.
|
| + AK_FORCE_INLINE void initWithPtNodePos(const int ptNodePos) {
|
| + if (ptNodePos == NOT_A_DICT_POS) {
|
| + mReadingState.mPos = NOT_A_DICT_POS;
|
| + } else {
|
| + mIsError = false;
|
| + mReadingState.mPos = ptNodePos;
|
| + mReadingState.mRemainingPtNodeCountInThisArray = 1;
|
| + mReadingState.mTotalCodePointCountSinceInitialization = 0;
|
| + mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
|
| + mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
|
| + mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
|
| + mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
|
| + mReadingStateStack.clear();
|
| + }
|
| + }
|
| +
|
| + AK_FORCE_INLINE const PtNodeParams getPtNodeParams() const {
|
| + if (isEnd()) {
|
| + return PtNodeParams();
|
| + }
|
| + return mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(mReadingState.mPos);
|
| + }
|
| +
|
| + AK_FORCE_INLINE bool isValidTerminalNode(const PtNodeParams &ptNodeParams) const {
|
| + return !isEnd() && !ptNodeParams.isDeleted() && ptNodeParams.isTerminal();
|
| + }
|
| +
|
| + AK_FORCE_INLINE bool isMatchedCodePoint(const PtNodeParams &ptNodeParams, const int index,
|
| + const int codePoint) const {
|
| + return ptNodeParams.getCodePoints()[index] == codePoint;
|
| + }
|
| +
|
| + // Return code point count exclude the last read node's code points.
|
| + AK_FORCE_INLINE int getPrevTotalCodePointCount() const {
|
| + return mReadingState.mTotalCodePointCountSinceInitialization;
|
| + }
|
| +
|
| + // Return code point count include the last read node's code points.
|
| + AK_FORCE_INLINE int getTotalCodePointCount(const PtNodeParams &ptNodeParams) const {
|
| + return mReadingState.mTotalCodePointCountSinceInitialization
|
| + + ptNodeParams.getCodePointCount();
|
| + }
|
| +
|
| + AK_FORCE_INLINE void fetchMergedNodeCodePointsInReverseOrder(const PtNodeParams &ptNodeParams,
|
| + const int index, int *const outCodePoints) const {
|
| + const int nodeCodePointCount = ptNodeParams.getCodePointCount();
|
| + const int *const nodeCodePoints = ptNodeParams.getCodePoints();
|
| + for (int i = 0; i < nodeCodePointCount; ++i) {
|
| + outCodePoints[index + i] = nodeCodePoints[nodeCodePointCount - 1 - i];
|
| + }
|
| + }
|
| +
|
| + AK_FORCE_INLINE void readNextSiblingNode(const PtNodeParams &ptNodeParams) {
|
| + mReadingState.mRemainingPtNodeCountInThisArray -= 1;
|
| + mReadingState.mPos = ptNodeParams.getSiblingNodePos();
|
| + if (mReadingState.mRemainingPtNodeCountInThisArray <= 0) {
|
| + // All nodes in the current node array have been read.
|
| + followForwardLink();
|
| + }
|
| + }
|
| +
|
| + // Read the first child node of the current node.
|
| + AK_FORCE_INLINE void readChildNode(const PtNodeParams &ptNodeParams) {
|
| + if (ptNodeParams.hasChildren()) {
|
| + mReadingState.mTotalCodePointCountSinceInitialization +=
|
| + ptNodeParams.getCodePointCount();
|
| + mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
|
| + mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
|
| + mReadingState.mPos = ptNodeParams.getChildrenPos();
|
| + mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
|
| + // Read children node array.
|
| + nextPtNodeArray();
|
| + } else {
|
| + mReadingState.mPos = NOT_A_DICT_POS;
|
| + }
|
| + }
|
| +
|
| + // Read the parent node of the current node.
|
| + AK_FORCE_INLINE void readParentNode(const PtNodeParams &ptNodeParams) {
|
| + if (ptNodeParams.getParentPos() != NOT_A_DICT_POS) {
|
| + mReadingState.mTotalCodePointCountSinceInitialization +=
|
| + ptNodeParams.getCodePointCount();
|
| + mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
|
| + mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
|
| + mReadingState.mRemainingPtNodeCountInThisArray = 1;
|
| + mReadingState.mPos = ptNodeParams.getParentPos();
|
| + mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
|
| + mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
|
| + } else {
|
| + mReadingState.mPos = NOT_A_DICT_POS;
|
| + }
|
| + }
|
| +
|
| + AK_FORCE_INLINE int getPosOfLastForwardLinkField() const {
|
| + return mReadingState.mPosOfLastForwardLinkField;
|
| + }
|
| +
|
| + AK_FORCE_INLINE int getPosOfLastPtNodeArrayHead() const {
|
| + return mReadingState.mPosOfThisPtNodeArrayHead;
|
| + }
|
| +
|
| + bool traverseAllPtNodesInPostorderDepthFirstManner(TraversingEventListener *const listener);
|
| +
|
| + bool traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
|
| + TraversingEventListener *const listener);
|
| +
|
| + int getCodePointsAndProbabilityAndReturnCodePointCount(const int maxCodePointCount,
|
| + int *const outCodePoints, int *const outUnigramProbability);
|
| +
|
| + int getTerminalPtNodePositionOfWord(const int *const inWord, const int length,
|
| + const bool forceLowerCaseSearch);
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(DynamicPtReadingHelper);
|
| +
|
| + // This class encapsulates the reading state of a position in the dictionary. It points at a
|
| + // specific PtNode in the dictionary.
|
| + class PtNodeReadingState {
|
| + public:
|
| + // Note that copy constructor and assignment operator are used for this class to use
|
| + // std::vector.
|
| + PtNodeReadingState() : mPos(NOT_A_DICT_POS), mRemainingPtNodeCountInThisArray(0),
|
| + mTotalCodePointCountSinceInitialization(0), mTotalPtNodeIndexInThisArrayChain(0),
|
| + mPtNodeArrayIndexInThisArrayChain(0), mPosOfLastForwardLinkField(NOT_A_DICT_POS),
|
| + mPosOfThisPtNodeArrayHead(NOT_A_DICT_POS) {}
|
| +
|
| + int mPos;
|
| + // Remaining node count in the current array.
|
| + int mRemainingPtNodeCountInThisArray;
|
| + int mTotalCodePointCountSinceInitialization;
|
| + // Counter of PtNodes used to avoid infinite loops caused by broken or malicious links.
|
| + int mTotalPtNodeIndexInThisArrayChain;
|
| + // Counter of PtNode arrays used to avoid infinite loops caused by cyclic links of empty
|
| + // PtNode arrays.
|
| + int mPtNodeArrayIndexInThisArrayChain;
|
| + int mPosOfLastForwardLinkField;
|
| + int mPosOfThisPtNodeArrayHead;
|
| + };
|
| +
|
| + static const int MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP;
|
| + static const int MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP;
|
| + static const size_t MAX_READING_STATE_STACK_SIZE;
|
| +
|
| + // TODO: Introduce error code to track what caused the error.
|
| + bool mIsError;
|
| + PtNodeReadingState mReadingState;
|
| + const PtNodeReader *const mPtNodeReader;
|
| + const PtNodeArrayReader *const mPtNodeArrayReader;
|
| + std::vector<PtNodeReadingState> mReadingStateStack;
|
| +
|
| + void nextPtNodeArray();
|
| +
|
| + void followForwardLink();
|
| +
|
| + AK_FORCE_INLINE void pushReadingStateToStack() {
|
| + if (mReadingStateStack.size() > MAX_READING_STATE_STACK_SIZE) {
|
| + AKLOGI("Reading state stack overflow. Max size: %zd", MAX_READING_STATE_STACK_SIZE);
|
| + ASSERT(false);
|
| + mIsError = true;
|
| + mReadingState.mPos = NOT_A_DICT_POS;
|
| + } else {
|
| + mReadingStateStack.push_back(mReadingState);
|
| + }
|
| + }
|
| +
|
| + AK_FORCE_INLINE void popReadingStateFromStack() {
|
| + if (mReadingStateStack.empty()) {
|
| + mReadingState.mPos = NOT_A_DICT_POS;
|
| + } else {
|
| + mReadingState = mReadingStateStack.back();
|
| + mReadingStateStack.pop_back();
|
| + }
|
| + }
|
| +};
|
| +} // namespace latinime
|
| +#endif /* LATINIME_DYNAMIC_PT_READING_HELPER_H */
|
|
|