diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
index 41b9a11b117ab906eef8be99f37c543ef7785a42..d8ed198f6a9532ad2f8c0b4d468b668c5894a968 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
@@ -268,8 +268,8 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePo
         return false;
     }
     const CodePointArrayView codePointArrayView(codePointsToAdd, codePointCountToAdd);
-    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView.data(),
-            codePointArrayView.size(), unigramProperty, &addedNewUnigram)) {
+    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView, unigramProperty,
+            &addedNewUnigram)) {
         if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
             mUnigramCount++;
         }
@@ -283,8 +283,8 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePo
             }
             for (const auto &shortcut : unigramProperty->getShortcuts()) {
                 if (!mUpdatingHelper.addShortcutTarget(wordPos,
-                        shortcut.getTargetCodePoints()->data(),
-                        shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
+                        CodePointArrayView(*shortcut.getTargetCodePoints()),
+                        shortcut.getProbability())) {
                     AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
                             "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
                             shortcut.getProbability());
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp
index 086d98b4affa02497baba2ded6da2190a41368a3..40782a44f77af2a407fa03f2611dd1f1b0af2095 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp
@@ -218,9 +218,9 @@ int DynamicPtReadingHelper::getCodePointsAndProbabilityAndReturnCodePointCount(
 }
 
 int DynamicPtReadingHelper::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) {
+        const size_t length, const bool forceLowerCaseSearch) {
     int searchCodePoints[length];
-    for (int i = 0; i < length; ++i) {
+    for (size_t i = 0; i < length; ++i) {
         searchCodePoints[i] = forceLowerCaseSearch ? CharUtils::toLowerCase(inWord[i]) : inWord[i];
     }
     while (!isEnd()) {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
index b7262581a822d635178f0728610f1f358a8371c2..9a7abc97f88d266621ffe35d32e341d5b93e0a7d 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
@@ -138,12 +138,12 @@ class DynamicPtReadingHelper {
     }
 
     // Return code point count exclude the last read node's code points.
-    AK_FORCE_INLINE int getPrevTotalCodePointCount() const {
+    AK_FORCE_INLINE size_t 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 {
+    AK_FORCE_INLINE size_t getTotalCodePointCount(const PtNodeParams &ptNodeParams) const {
         return mReadingState.mTotalCodePointCountSinceInitialization
                 + ptNodeParams.getCodePointCount();
     }
@@ -214,7 +214,7 @@ class DynamicPtReadingHelper {
     int getCodePointsAndProbabilityAndReturnCodePointCount(const int maxCodePointCount,
             int *const outCodePoints, int *const outUnigramProbability);
 
-    int getTerminalPtNodePositionOfWord(const int *const inWord, const int length,
+    int getTerminalPtNodePositionOfWord(const int *const inWord, const size_t length,
             const bool forceLowerCaseSearch);
 
  private:
@@ -234,7 +234,7 @@ class DynamicPtReadingHelper {
         int mPos;
         // Remaining node count in the current array.
         int mRemainingPtNodeCountInThisArray;
-        int mTotalCodePointCountSinceInitialization;
+        size_t 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
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
index 3c62e2e56149144bef2d66a53d996fcd4f4778bb..3b58d7d6d48a718cd7f98cbd7a0e423a7ecf8363 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
@@ -28,17 +28,16 @@ namespace latinime {
 
 const int DynamicPtUpdatingHelper::CHILDREN_POSITION_FIELD_SIZE = 3;
 
-bool DynamicPtUpdatingHelper::addUnigramWord(
-        DynamicPtReadingHelper *const readingHelper,
-        const int *const wordCodePoints, const int codePointCount,
-        const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram) {
+bool DynamicPtUpdatingHelper::addUnigramWord(DynamicPtReadingHelper *const readingHelper,
+        const CodePointArrayView wordCodePoints, const UnigramProperty *const unigramProperty,
+        bool *const outAddedNewUnigram) {
     int parentPos = NOT_A_DICT_POS;
     while (!readingHelper->isEnd()) {
         const PtNodeParams ptNodeParams(readingHelper->getPtNodeParams());
         if (!ptNodeParams.isValid()) {
             break;
         }
-        const int matchedCodePointCount = readingHelper->getPrevTotalCodePointCount();
+        const size_t matchedCodePointCount = readingHelper->getPrevTotalCodePointCount();
         if (!readingHelper->isMatchedCodePoint(ptNodeParams, 0 /* index */,
                 wordCodePoints[matchedCodePointCount])) {
             // The first code point is different from target code point. Skip this node and read
@@ -47,26 +46,25 @@ bool DynamicPtUpdatingHelper::addUnigramWord(
             continue;
         }
         // Check following merged node code points.
-        const int nodeCodePointCount = ptNodeParams.getCodePointCount();
-        for (int j = 1; j < nodeCodePointCount; ++j) {
-            const int nextIndex = matchedCodePointCount + j;
-            if (nextIndex >= codePointCount || !readingHelper->isMatchedCodePoint(ptNodeParams, j,
-                    wordCodePoints[matchedCodePointCount + j])) {
+        const size_t nodeCodePointCount = ptNodeParams.getCodePointArrayView().size();
+        for (size_t j = 1; j < nodeCodePointCount; ++j) {
+            const size_t nextIndex = matchedCodePointCount + j;
+            if (nextIndex >= wordCodePoints.size()
+                    || !readingHelper->isMatchedCodePoint(ptNodeParams, j,
+                            wordCodePoints[matchedCodePointCount + j])) {
                 *outAddedNewUnigram = true;
                 return reallocatePtNodeAndAddNewPtNodes(&ptNodeParams, j, unigramProperty,
-                        wordCodePoints + matchedCodePointCount,
-                        codePointCount - matchedCodePointCount);
+                        wordCodePoints.skip(matchedCodePointCount));
             }
         }
         // All characters are matched.
-        if (codePointCount == readingHelper->getTotalCodePointCount(ptNodeParams)) {
+        if (wordCodePoints.size() == readingHelper->getTotalCodePointCount(ptNodeParams)) {
             return setPtNodeProbability(&ptNodeParams, unigramProperty, outAddedNewUnigram);
         }
         if (!ptNodeParams.hasChildren()) {
             *outAddedNewUnigram = true;
             return createChildrenPtNodeArrayAndAChildPtNode(&ptNodeParams, unigramProperty,
-                    wordCodePoints + readingHelper->getTotalCodePointCount(ptNodeParams),
-                    codePointCount - readingHelper->getTotalCodePointCount(ptNodeParams));
+                    wordCodePoints.skip(readingHelper->getTotalCodePointCount(ptNodeParams)));
         }
         // Advance to the children nodes.
         parentPos = ptNodeParams.getHeadPos();
@@ -79,9 +77,8 @@ bool DynamicPtUpdatingHelper::addUnigramWord(
     int pos = readingHelper->getPosOfLastForwardLinkField();
     *outAddedNewUnigram = true;
     return createAndInsertNodeIntoPtNodeArray(parentPos,
-            wordCodePoints + readingHelper->getPrevTotalCodePointCount(),
-            codePointCount - readingHelper->getPrevTotalCodePointCount(),
-            unigramProperty, &pos);
+            wordCodePoints.skip(readingHelper->getPrevTotalCodePointCount()), unigramProperty,
+            &pos);
 }
 
 bool DynamicPtUpdatingHelper::addNgramEntry(const PtNodePosArrayView prevWordsPtNodePos,
@@ -120,23 +117,21 @@ bool DynamicPtUpdatingHelper::removeNgramEntry(const PtNodePosArrayView prevWord
 }
 
 bool DynamicPtUpdatingHelper::addShortcutTarget(const int wordPos,
-        const int *const targetCodePoints, const int targetCodePointCount,
-        const int shortcutProbability) {
+        const CodePointArrayView targetCodePoints, const int shortcutProbability) {
     const PtNodeParams ptNodeParams(mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos));
-    return mPtNodeWriter->addShortcutTarget(&ptNodeParams, targetCodePoints, targetCodePointCount,
-            shortcutProbability);
+    return mPtNodeWriter->addShortcutTarget(&ptNodeParams, targetCodePoints.data(),
+            targetCodePoints.size(), shortcutProbability);
 }
 
 bool DynamicPtUpdatingHelper::createAndInsertNodeIntoPtNodeArray(const int parentPos,
-        const int *const nodeCodePoints, const int nodeCodePointCount,
-        const UnigramProperty *const unigramProperty, int *const forwardLinkFieldPos) {
+        const CodePointArrayView ptNodeCodePoints, const UnigramProperty *const unigramProperty,
+        int *const forwardLinkFieldPos) {
     const int newPtNodeArrayPos = mBuffer->getTailPosition();
     if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer,
             newPtNodeArrayPos, forwardLinkFieldPos)) {
         return false;
     }
-    return createNewPtNodeArrayWithAChildPtNode(parentPos, nodeCodePoints, nodeCodePointCount,
-            unigramProperty);
+    return createNewPtNodeArrayWithAChildPtNode(parentPos, ptNodeCodePoints, unigramProperty);
 }
 
 bool DynamicPtUpdatingHelper::setPtNodeProbability(const PtNodeParams *const originalPtNodeParams,
@@ -153,8 +148,7 @@ bool DynamicPtUpdatingHelper::setPtNodeProbability(const PtNodeParams *const ori
         const PtNodeParams ptNodeParamsToWrite(getUpdatedPtNodeParams(originalPtNodeParams,
                 unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
                 true /* isTerminal */, originalPtNodeParams->getParentPos(),
-                originalPtNodeParams->getCodePointCount(), originalPtNodeParams->getCodePoints(),
-                unigramProperty->getProbability()));
+                originalPtNodeParams->getCodePointArrayView(), unigramProperty->getProbability()));
         if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
                 unigramProperty, &writingPos)) {
             return false;
@@ -168,17 +162,17 @@ bool DynamicPtUpdatingHelper::setPtNodeProbability(const PtNodeParams *const ori
 
 bool DynamicPtUpdatingHelper::createChildrenPtNodeArrayAndAChildPtNode(
         const PtNodeParams *const parentPtNodeParams, const UnigramProperty *const unigramProperty,
-        const int *const codePoints, const int codePointCount) {
+        const CodePointArrayView codePoints) {
     const int newPtNodeArrayPos = mBuffer->getTailPosition();
     if (!mPtNodeWriter->updateChildrenPosition(parentPtNodeParams, newPtNodeArrayPos)) {
         return false;
     }
     return createNewPtNodeArrayWithAChildPtNode(parentPtNodeParams->getHeadPos(), codePoints,
-            codePointCount, unigramProperty);
+            unigramProperty);
 }
 
 bool DynamicPtUpdatingHelper::createNewPtNodeArrayWithAChildPtNode(
-        const int parentPtNodePos, const int *const nodeCodePoints, const int nodeCodePointCount,
+        const int parentPtNodePos, const CodePointArrayView ptNodeCodePoints,
         const UnigramProperty *const unigramProperty) {
     int writingPos = mBuffer->getTailPosition();
     if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer,
@@ -187,8 +181,7 @@ bool DynamicPtUpdatingHelper::createNewPtNodeArrayWithAChildPtNode(
     }
     const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
             unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(), true /* isTerminal */,
-            parentPtNodePos, nodeCodePointCount, nodeCodePoints,
-            unigramProperty->getProbability()));
+            parentPtNodePos, ptNodeCodePoints, unigramProperty->getProbability()));
     if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
             unigramProperty, &writingPos)) {
         return false;
@@ -202,9 +195,9 @@ bool DynamicPtUpdatingHelper::createNewPtNodeArrayWithAChildPtNode(
 
 // Returns whether the dictionary updating was succeeded or not.
 bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
-        const PtNodeParams *const reallocatingPtNodeParams, const int overlappingCodePointCount,
-        const UnigramProperty *const unigramProperty, const int *const newNodeCodePoints,
-        const int newNodeCodePointCount) {
+        const PtNodeParams *const reallocatingPtNodeParams, const size_t overlappingCodePointCount,
+        const UnigramProperty *const unigramProperty,
+        const CodePointArrayView newPtNodeCodePoints) {
     // When addsExtraChild is true, split the reallocating PtNode and add new child.
     // Reallocating PtNode: abcde, newNode: abcxy.
     // abc (1st, not terminal) __ de (2nd)
@@ -212,16 +205,18 @@ bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
     // Otherwise, this method makes 1st part terminal and write information in unigramProperty.
     // Reallocating PtNode: abcde, newNode: abc.
     // abc (1st, terminal) __ de (2nd)
-    const bool addsExtraChild = newNodeCodePointCount > overlappingCodePointCount;
+    const bool addsExtraChild = newPtNodeCodePoints.size() > overlappingCodePointCount;
     const int firstPartOfReallocatedPtNodePos = mBuffer->getTailPosition();
     int writingPos = firstPartOfReallocatedPtNodePos;
     // Write the 1st part of the reallocating node. The children position will be updated later
     // with actual children position.
+    const CodePointArrayView firstPtNodeCodePoints =
+            reallocatingPtNodeParams->getCodePointArrayView().limit(overlappingCodePointCount);
     if (addsExtraChild) {
         const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
                 false /* isNotAWord */, false /* isBlacklisted */, false /* isTerminal */,
-                reallocatingPtNodeParams->getParentPos(), overlappingCodePointCount,
-                reallocatingPtNodeParams->getCodePoints(), NOT_A_PROBABILITY));
+                reallocatingPtNodeParams->getParentPos(), firstPtNodeCodePoints,
+                NOT_A_PROBABILITY));
         if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&ptNodeParamsToWrite, &writingPos)) {
             return false;
         }
@@ -229,8 +224,7 @@ bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
         const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
                 unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
                 true /* isTerminal */, reallocatingPtNodeParams->getParentPos(),
-                overlappingCodePointCount, reallocatingPtNodeParams->getCodePoints(),
-                unigramProperty->getProbability()));
+                firstPtNodeCodePoints, unigramProperty->getProbability()));
         if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
                 unigramProperty, &writingPos)) {
             return false;
@@ -248,8 +242,7 @@ bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
     const PtNodeParams childPartPtNodeParams(getUpdatedPtNodeParams(reallocatingPtNodeParams,
             reallocatingPtNodeParams->isNotAWord(), reallocatingPtNodeParams->isBlacklisted(),
             reallocatingPtNodeParams->isTerminal(), firstPartOfReallocatedPtNodePos,
-            reallocatingPtNodeParams->getCodePointCount() - overlappingCodePointCount,
-            reallocatingPtNodeParams->getCodePoints() + overlappingCodePointCount,
+            reallocatingPtNodeParams->getCodePointArrayView().skip(overlappingCodePointCount),
             reallocatingPtNodeParams->getProbability()));
     if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&childPartPtNodeParams, &writingPos)) {
         return false;
@@ -258,8 +251,8 @@ bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
         const PtNodeParams extraChildPtNodeParams(getPtNodeParamsForNewPtNode(
                 unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
                 true /* isTerminal */, firstPartOfReallocatedPtNodePos,
-                newNodeCodePointCount - overlappingCodePointCount,
-                newNodeCodePoints + overlappingCodePointCount, unigramProperty->getProbability()));
+                newPtNodeCodePoints.skip(overlappingCodePointCount),
+                unigramProperty->getProbability()));
         if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&extraChildPtNodeParams,
                 unigramProperty, &writingPos)) {
             return false;
@@ -282,26 +275,24 @@ bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
 }
 
 const PtNodeParams DynamicPtUpdatingHelper::getUpdatedPtNodeParams(
-        const PtNodeParams *const originalPtNodeParams,
-        const bool isNotAWord, const bool isBlacklisted, const bool isTerminal, const int parentPos,
-        const int codePointCount, const int *const codePoints, const int probability) const {
+        const PtNodeParams *const originalPtNodeParams, const bool isNotAWord,
+        const bool isBlacklisted, const bool isTerminal, const int parentPos,
+        const CodePointArrayView codePoints, const int probability) const {
     const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags(
             isBlacklisted, isNotAWord, isTerminal, false /* hasShortcutTargets */,
-            false /* hasBigrams */, codePointCount > 1 /* hasMultipleChars */,
+            false /* hasBigrams */, codePoints.size() > 1u /* hasMultipleChars */,
             CHILDREN_POSITION_FIELD_SIZE);
-    return PtNodeParams(originalPtNodeParams, flags, parentPos, codePointCount, codePoints,
-            probability);
+    return PtNodeParams(originalPtNodeParams, flags, parentPos, codePoints, probability);
 }
 
-const PtNodeParams DynamicPtUpdatingHelper::getPtNodeParamsForNewPtNode(
-        const bool isNotAWord, const bool isBlacklisted, const bool isTerminal,
-        const int parentPos, const int codePointCount, const int *const codePoints,
-        const int probability) const {
+const PtNodeParams DynamicPtUpdatingHelper::getPtNodeParamsForNewPtNode(const bool isNotAWord,
+        const bool isBlacklisted, const bool isTerminal, const int parentPos,
+        const CodePointArrayView codePoints, const int probability) const {
     const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags(
             isBlacklisted, isNotAWord, isTerminal, false /* hasShortcutTargets */,
-            false /* hasBigrams */, codePointCount > 1 /* hasMultipleChars */,
+            false /* hasBigrams */, codePoints.size() > 1u /* hasMultipleChars */,
             CHILDREN_POSITION_FIELD_SIZE);
-    return PtNodeParams(flags, parentPos, codePointCount, codePoints, probability);
+    return PtNodeParams(flags, parentPos, codePoints, probability);
 }
 
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
index b61d9dbe3e4431581e6e1b8cebc34a17a1831d5d..710047e8c3595b80766edbbeb7a2435127f44c81 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
@@ -40,8 +40,8 @@ class DynamicPtUpdatingHelper {
 
     // Add a word to the dictionary. If the word already exists, update the probability.
     bool addUnigramWord(DynamicPtReadingHelper *const readingHelper,
-            const int *const wordCodePoints, const int codePointCount,
-            const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram);
+            const CodePointArrayView wordCodePoints, const UnigramProperty *const unigramProperty,
+            bool *const outAddedNewUnigram);
 
     // TODO: Remove after stopping supporting v402.
     // Add an n-gram entry.
@@ -53,8 +53,8 @@ class DynamicPtUpdatingHelper {
     bool removeNgramEntry(const PtNodePosArrayView prevWordsPtNodePos, const int wordPos);
 
     // Add a shortcut target.
-    bool addShortcutTarget(const int wordPos, const int *const targetCodePoints,
-            const int targetCodePointCount, const int shortcutProbability);
+    bool addShortcutTarget(const int wordPos, const CodePointArrayView targetCodePoints,
+            const int shortcutProbability);
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPtUpdatingHelper);
@@ -65,33 +65,32 @@ class DynamicPtUpdatingHelper {
     const PtNodeReader *const mPtNodeReader;
     PtNodeWriter *const mPtNodeWriter;
 
-    bool createAndInsertNodeIntoPtNodeArray(const int parentPos, const int *const nodeCodePoints,
-            const int nodeCodePointCount, const UnigramProperty *const unigramProperty,
+    bool createAndInsertNodeIntoPtNodeArray(const int parentPos,
+            const CodePointArrayView ptNodeCodePoints, const UnigramProperty *const unigramProperty,
             int *const forwardLinkFieldPos);
 
     bool setPtNodeProbability(const PtNodeParams *const originalPtNodeParams,
             const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram);
 
     bool createChildrenPtNodeArrayAndAChildPtNode(const PtNodeParams *const parentPtNodeParams,
-            const UnigramProperty *const unigramProperty, const int *const codePoints,
-            const int codePointCount);
+            const UnigramProperty *const unigramProperty,
+            const CodePointArrayView remainingCodePoints);
 
-    bool createNewPtNodeArrayWithAChildPtNode(const int parentPos, const int *const nodeCodePoints,
-            const int nodeCodePointCount, const UnigramProperty *const unigramProperty);
+    bool createNewPtNodeArrayWithAChildPtNode(const int parentPos,
+            const CodePointArrayView ptNodeCodePoints,
+            const UnigramProperty *const unigramProperty);
 
-    bool reallocatePtNodeAndAddNewPtNodes(
-            const PtNodeParams *const reallocatingPtNodeParams, const int overlappingCodePointCount,
-            const UnigramProperty *const unigramProperty, const int *const newNodeCodePoints,
-            const int newNodeCodePointCount);
+    bool reallocatePtNodeAndAddNewPtNodes(const PtNodeParams *const reallocatingPtNodeParams,
+            const size_t overlappingCodePointCount, const UnigramProperty *const unigramProperty,
+            const CodePointArrayView newPtNodeCodePoints);
 
     const PtNodeParams getUpdatedPtNodeParams(const PtNodeParams *const originalPtNodeParams,
             const bool isNotAWord, const bool isBlacklisted, const bool isTerminal,
-            const int parentPos, const int codePointCount,
-            const int *const codePoints, const int probability) const;
+            const int parentPos, const CodePointArrayView codePoints, const int probability) const;
 
     const PtNodeParams getPtNodeParamsForNewPtNode(const bool isNotAWord, const bool isBlacklisted,
-            const bool isTerminal, const int parentPos,
-            const int codePointCount, const int *const codePoints, const int probability) const;
+            const bool isTerminal, const int parentPos, const CodePointArrayView codePoints,
+            const int probability) const;
 };
 } // namespace latinime
 #endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_UPDATING_HELPER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
index c12fed3248c1eb49632692bb12daa4b676e1524a..3ff1829bd864d1a65af37fa7be23adddce139490 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
@@ -89,9 +89,9 @@ class PtNodeParams {
     // Construct new params by updating existing PtNode params.
     PtNodeParams(const PtNodeParams *const ptNodeParams,
             const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos,
-            const int codePointCount, const int *const codePoints, const int probability)
+            const CodePointArrayView codePoints, const int probability)
             : mHeadPos(ptNodeParams->getHeadPos()), mFlags(flags), mHasMovedFlag(true),
-              mParentPos(parentPos), mCodePointCount(codePointCount), mCodePoints(),
+              mParentPos(parentPos), mCodePointCount(codePoints.size()), mCodePoints(),
               mTerminalIdFieldPos(ptNodeParams->getTerminalIdFieldPos()),
               mTerminalId(ptNodeParams->getTerminalId()),
               mProbabilityFieldPos(ptNodeParams->getProbabilityFieldPos()),
@@ -102,20 +102,20 @@ class PtNodeParams {
               mShortcutPos(ptNodeParams->getShortcutPos()),
               mBigramPos(ptNodeParams->getBigramsPos()),
               mSiblingPos(ptNodeParams->getSiblingNodePos()) {
-        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
+        memcpy(mCodePoints, codePoints.data(), sizeof(int) * mCodePointCount);
     }
 
     PtNodeParams(const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos,
-            const int codePointCount, const int *const codePoints, const int probability)
+            const CodePointArrayView codePoints, const int probability)
             : mHeadPos(NOT_A_DICT_POS), mFlags(flags), mHasMovedFlag(true), mParentPos(parentPos),
-              mCodePointCount(codePointCount), mCodePoints(),
+              mCodePointCount(codePoints.size()), mCodePoints(),
               mTerminalIdFieldPos(NOT_A_DICT_POS),
               mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID),
               mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability),
               mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(NOT_A_DICT_POS),
               mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(NOT_A_DICT_POS),
               mBigramPos(NOT_A_DICT_POS), mSiblingPos(NOT_A_DICT_POS) {
-        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
+        memcpy(mCodePoints, codePoints.data(), sizeof(int) * mCodePointCount);
     }
 
     AK_FORCE_INLINE bool isValid() const {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 2af218ab6fb0f9f95295d5f90ffaf0e2e098bfc5..8d41356795d001110b9f6fd094186bef0f2c5459 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -227,8 +227,8 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePo
         return false;
     }
     const CodePointArrayView codePointArrayView(codePointsToAdd, codePointCountToAdd);
-    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView.data(),
-            codePointArrayView.size(), unigramProperty, &addedNewUnigram)) {
+    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView, unigramProperty,
+            &addedNewUnigram)) {
         if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
             mUnigramCount++;
         }
@@ -243,8 +243,8 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePo
                     mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(wordId);
             for (const auto &shortcut : unigramProperty->getShortcuts()) {
                 if (!mUpdatingHelper.addShortcutTarget(wordPos,
-                        shortcut.getTargetCodePoints()->data(),
-                        shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
+                        CodePointArrayView(*shortcut.getTargetCodePoints()),
+                        shortcut.getProbability())) {
                     AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
                             "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
                             shortcut.getProbability());